Revamped image and introduced byte* interface (Brad, bs_1.patch with minor modifications by ahu)

v0.27.3
Andreas Huggel 21 years ago
parent 964e1df085
commit 9d72b7d1ec

@ -104,3 +104,12 @@
/* Define to `unsigned' if <sys/types.h> does not define. */ /* Define to `unsigned' if <sys/types.h> does not define. */
#undef size_t #undef size_t
/* File path seperator */
#ifdef _MSC_VER
#define SEPERATOR_STR "\\"
#define SEPERATOR_CHR '\\'
#else
#define SEPERATOR_STR "/"
#define SEPERATOR_CHR '/'
#endif

@ -61,13 +61,19 @@ BINSRC = addmoddel.cpp exifcomment.cpp exifprint.cpp ifd-test.cpp \
# State the main source file of the Exiv2 application here # State the main source file of the Exiv2 application here
EXIV2MAIN = exiv2.cpp EXIV2MAIN = exiv2.cpp
# Add additional source files of the real application to this list # Add additional source files of the Exiv2 application to this list
EXIV2SRC = actions.cpp utils.cpp EXIV2SRC = actions.cpp utils.cpp
# C source files of the application # C source files of the Exiv2 application
ifndef HAVE_TIMEGM ifndef HAVE_TIMEGM
EXIVCSRC = localtime.c EXIVCSRC = localtime.c
endif endif
# State the main source file of the metacopy application here
MCMAIN = metacopy.cpp
# Add additional source files of the metacopy application to this list
MCSRC = utils.cpp
# ****************************************************************************** # ******************************************************************************
# Library # Library
@ -101,7 +107,8 @@ HDR = $(CCHDR)
OBJ = $(CCOBJ) OBJ = $(CCOBJ)
SOBJ = $(CCSOBJ) SOBJ = $(CCSOBJ)
DEP = $(CCSRC:%.cpp=.%.d) $(BINSRC:%.cpp=.%.d) \ DEP = $(CCSRC:%.cpp=.%.d) $(BINSRC:%.cpp=.%.d) \
$(EXIV2MAIN:%.cpp=.%.d) $(EXIV2SRC:%.cpp=.%.d) $(EXIVCSRC:%.c=.%.d) $(EXIV2MAIN:%.cpp=.%.d) $(EXIV2SRC:%.cpp=.%.d) $(EXIVCSRC:%.c=.%.d) \
$(MCMAIN:%.cpp=.%.d) $(MCSRC:%.cpp=.%.d)
BINOBJ = $(BINSRC:.cpp=.o) BINOBJ = $(BINSRC:.cpp=.o)
BINARY = $(BINSRC:.cpp=) BINARY = $(BINSRC:.cpp=)
@ -109,6 +116,10 @@ BINARY = $(BINSRC:.cpp=)
EXIV2OBJ = $(EXIV2MAIN:.cpp=.o) $(EXIV2SRC:.cpp=.o) $(EXIVCSRC:.c=.o) EXIV2OBJ = $(EXIV2MAIN:.cpp=.o) $(EXIV2SRC:.cpp=.o) $(EXIVCSRC:.c=.o)
EXIV2BIN = $(EXIV2MAIN:.cpp=) EXIV2BIN = $(EXIV2MAIN:.cpp=)
MCOBJ = $(MCMAIN:.cpp=.o) $(MCSRC:.cpp=.o)
MCBIN = $(MCMAIN:.cpp=)
ARCHIVE = lib$(LIBNAME)$(ARCHIVE_SUFFIX) ARCHIVE = lib$(LIBNAME)$(ARCHIVE_SUFFIX)
SHAREDLIB = lib$(LIBNAME)$(SHAREDLIB_SUFFIX) SHAREDLIB = lib$(LIBNAME)$(SHAREDLIB_SUFFIX)
@ -179,6 +190,9 @@ $(BINARY): %: %.o
$(EXIV2BIN): %: %.o $(EXIV2BIN): %: %.o
$(CXX) $(CXXFLAGS) $(EXIV2OBJ) $(LDLIBS) $(LDFLAGS_BIN) -o $@ $(CXX) $(CXXFLAGS) $(EXIV2OBJ) $(LDLIBS) $(LDFLAGS_BIN) -o $@
$(MCBIN): %: %.o
$(CXX) $(CXXFLAGS) $(MCOBJ) $(LDLIBS) $(LDFLAGS_BIN) -o $@
mn.cpp: ./mn.sh mn.cpp: ./mn.sh
./mn.sh ./mn.sh
@ -217,7 +231,9 @@ endif
$(EXIV2BIN): lib $(EXIV2OBJ) $(EXIV2BIN): lib $(EXIV2OBJ)
bin: lib $(BINARY) $(EXIV2BIN) $(MCBIN): lib $(MCOBJ)
bin: lib $(BINARY) $(EXIV2BIN) $(MCBIN)
install: $(INSTALL) install: $(INSTALL)
$(INSTALL_DIRS) $(bindir) $(INSTALL_DIRS) $(bindir)
@ -278,7 +294,7 @@ check:
mostlyclean: mostlyclean:
$(RM) core $(RM) core
$(RM) $(CCSRC:.cpp=.ii) $(RM) $(CCSRC:.cpp=.ii)
$(RM) $(OBJ) $(SOBJ) $(BINOBJ) $(EXIV2OBJ) $(RM) $(OBJ) $(SOBJ) $(BINOBJ) $(EXIV2OBJ) $(MCOBJ)
$(RM) mn.o $(RM) mn.o
@if test -n "$(CXX_REPOSITORY)"; then \ @if test -n "$(CXX_REPOSITORY)"; then \
echo "rm -rf $(CXX_REPOSITORY)"; \ echo "rm -rf $(CXX_REPOSITORY)"; \
@ -287,7 +303,7 @@ mostlyclean:
clean: mostlyclean clean: mostlyclean
$(RM) $(ARCHIVE) $(SHAREDLIB) $(RM) $(ARCHIVE) $(SHAREDLIB)
$(RM) $(BINARY) $(EXIV2BIN) $(RM) $(BINARY) $(EXIV2BIN) $(MCBIN)
# Run `make distclean' from the top source directory to also remove # Run `make distclean' from the top source directory to also remove
# files created by configuring the program. # files created by configuring the program.

@ -20,13 +20,13 @@
*/ */
/* /*
File: actions.cpp File: actions.cpp
Version: $Name: $ $Revision: 1.30 $ Version: $Name: $ $Revision: 1.31 $
Author(s): Andreas Huggel (ahu) <ahuggel@gmx.net> Author(s): Andreas Huggel (ahu) <ahuggel@gmx.net>
History: 08-Dec-03, ahu: created History: 08-Dec-03, ahu: created
*/ */
// ***************************************************************************** // *****************************************************************************
#include "rcsid.hpp" #include "rcsid.hpp"
EXIV2_RCSID("@(#) $Name: $ $Revision: 1.30 $ $RCSfile: actions.cpp,v $") EXIV2_RCSID("@(#) $Name: $ $Revision: 1.31 $ $RCSfile: actions.cpp,v $")
// ***************************************************************************** // *****************************************************************************
// included header files // included header files
@ -513,7 +513,7 @@ namespace Action {
return 1; return 1;
} }
std::string newPath std::string newPath
= Util::dirname(path) + "/" + basename + Util::suffix(path); = Util::dirname(path) + SEPERATOR_STR + basename + Util::suffix(path);
if ( Util::dirname(newPath) == Util::dirname(path) if ( Util::dirname(newPath) == Util::dirname(path)
&& Util::basename(newPath) == Util::basename(path)) { && Util::basename(newPath) == Util::basename(path)) {
if (Params::instance().verbose_) { if (Params::instance().verbose_) {
@ -647,7 +647,7 @@ namespace Action {
int Extract::writeExifData(Exiv2::ExifData& exifData) const int Extract::writeExifData(Exiv2::ExifData& exifData) const
{ {
std::string exvPath = Util::dirname(path_) + "/" std::string exvPath = Util::dirname(path_) + SEPERATOR_STR
+ Util::basename(path_, true) + ".exv"; + Util::basename(path_, true) + ".exv";
if (Params::instance().verbose_) { if (Params::instance().verbose_) {
std::cout << "Writing Exif data to " << exvPath << "\n"; std::cout << "Writing Exif data to " << exvPath << "\n";
@ -669,7 +669,7 @@ namespace Action {
int Extract::writeThumbnail(const Exiv2::ExifData& exifData) const int Extract::writeThumbnail(const Exiv2::ExifData& exifData) const
{ {
int rc = 0; int rc = 0;
std::string thumb = Util::dirname(path_) + "/" std::string thumb = Util::dirname(path_) + SEPERATOR_STR
+ Util::basename(path_, true) + "-thumb"; + Util::basename(path_, true) + "-thumb";
std::string thumbExt = exifData.thumbnailExtension(); std::string thumbExt = exifData.thumbnailExtension();
if (thumbExt.empty()) { if (thumbExt.empty()) {
@ -709,7 +709,7 @@ namespace Action {
int Insert::run(const std::string& path) int Insert::run(const std::string& path)
try { try {
std::string exvPath = Util::dirname(path) + "/" std::string exvPath = Util::dirname(path) + SEPERATOR_STR
+ Util::basename(path, true) + ".exv"; + Util::basename(path, true) + ".exv";
Exiv2::ExifData exifData; Exiv2::ExifData exifData;
int rc = exifData.read(exvPath); int rc = exifData.read(exvPath);

@ -20,7 +20,7 @@
*/ */
/* /*
File: canonmn.cpp File: canonmn.cpp
Version: $Name: $ $Revision: 1.10 $ Version: $Name: $ $Revision: 1.11 $
Author(s): Andreas Huggel (ahu) <ahuggel@gmx.net> Author(s): Andreas Huggel (ahu) <ahuggel@gmx.net>
History: 18-Feb-04, ahu: created History: 18-Feb-04, ahu: created
07-Mar-04, ahu: isolated as a separate component 07-Mar-04, ahu: isolated as a separate component
@ -30,7 +30,7 @@
*/ */
// ***************************************************************************** // *****************************************************************************
#include "rcsid.hpp" #include "rcsid.hpp"
EXIV2_RCSID("@(#) $Name: $ $Revision: 1.10 $ $RCSfile: canonmn.cpp,v $") EXIV2_RCSID("@(#) $Name: $ $Revision: 1.11 $ $RCSfile: canonmn.cpp,v $")
// ***************************************************************************** // *****************************************************************************
// included header files // included header files
@ -553,7 +553,8 @@ namespace Exiv2 {
} }
if (value.count() < 26) return os; if (value.count() < 26) return os;
float fu = value.toLong(25); // Todo: why not use toFloat()?
float fu = static_cast<float>(value.toLong(25));
float len1 = value.toLong(23) / fu; float len1 = value.toLong(23) / fu;
float len2 = value.toLong(24) / fu; float len2 = value.toLong(24) / fu;
std::ostringstream oss; std::ostringstream oss;
@ -656,7 +657,7 @@ namespace Exiv2 {
// free functions // free functions
MakerNote* createCanonMakerNote(bool alloc, MakerNote* createCanonMakerNote(bool alloc,
const char* buf, const byte* buf,
long len, long len,
ByteOrder byteOrder, ByteOrder byteOrder,
long offset) long offset)

@ -23,10 +23,10 @@
@brief Canon MakerNote implemented according to the specification @brief Canon MakerNote implemented according to the specification
<a href="http://www.burren.cx/david/canon.html"> <a href="http://www.burren.cx/david/canon.html">
EXIF MakerNote of Canon</a> by David Burren EXIF MakerNote of Canon</a> by David Burren
@version $Name: $ $Revision: 1.8 $ @version $Name: $ $Revision: 1.9 $
@author Andreas Huggel (ahu) @author Andreas Huggel (ahu)
<a href="mailto:ahuggel@gmx.net">ahuggel@gmx.net</a> <a href="mailto:ahuggel@gmx.net">ahuggel@gmx.net</a>
@date 18-Feb-04, ahu: created @date 18-Feb-04, ahu: created<BR>
07-Mar-04, ahu: isolated as a separate component 07-Mar-04, ahu: isolated as a separate component
*/ */
#ifndef CANONMN_HPP_ #ifndef CANONMN_HPP_
@ -73,7 +73,7 @@ namespace Exiv2 {
this copy and is responsible to delete it! this copy and is responsible to delete it!
*/ */
MakerNote* createCanonMakerNote(bool alloc, MakerNote* createCanonMakerNote(bool alloc,
const char* buf, const byte* buf,
long len, long len,
ByteOrder byteOrder, ByteOrder byteOrder,
long offset); long offset);

@ -21,10 +21,10 @@
/*! /*!
@file error.hpp @file error.hpp
@brief Error class for exceptions @brief Error class for exceptions
@version $Name: $ $Revision: 1.2 $ @version $Name: $ $Revision: 1.3 $
@author Andreas Huggel (ahu) @author Andreas Huggel (ahu)
<a href="mailto:ahuggel@gmx.net">ahuggel@gmx.net</a> <a href="mailto:ahuggel@gmx.net">ahuggel@gmx.net</a>
@date 15-Jan-04, ahu: created @date 15-Jan-04, ahu: created<BR>
11-Feb-04, ahu: isolated as a component 11-Feb-04, ahu: isolated as a component
*/ */
#ifndef ERROR_HPP_ #ifndef ERROR_HPP_

@ -20,14 +20,14 @@
*/ */
/* /*
File: exif.cpp File: exif.cpp
Version: $Name: $ $Revision: 1.48 $ Version: $Name: $ $Revision: 1.49 $
Author(s): Andreas Huggel (ahu) <ahuggel@gmx.net> Author(s): Andreas Huggel (ahu) <ahuggel@gmx.net>
History: 26-Jan-04, ahu: created History: 26-Jan-04, ahu: created
11-Feb-04, ahu: isolated as a component 11-Feb-04, ahu: isolated as a component
*/ */
// ***************************************************************************** // *****************************************************************************
#include "rcsid.hpp" #include "rcsid.hpp"
EXIV2_RCSID("@(#) $Name: $ $Revision: 1.48 $ $RCSfile: exif.cpp,v $") EXIV2_RCSID("@(#) $Name: $ $Revision: 1.49 $ $RCSfile: exif.cpp,v $")
// Define DEBUG_MAKERNOTE to output debug information to std::cerr // Define DEBUG_MAKERNOTE to output debug information to std::cerr
#undef DEBUG_MAKERNOTE #undef DEBUG_MAKERNOTE
@ -173,7 +173,7 @@ namespace Exiv2 {
ifd_(ifd1, 0, false) ifd_(ifd1, 0, false)
{ {
if (rhs.pImage_ && rhs.size_ > 0) { if (rhs.pImage_ && rhs.size_ > 0) {
pImage_ = new char[rhs.size_]; pImage_ = new byte[rhs.size_];
memcpy(pImage_, rhs.pImage_, rhs.size_); memcpy(pImage_, rhs.pImage_, rhs.size_);
tiffHeader_.read(pImage_); tiffHeader_.read(pImage_);
ifd_.read(pImage_ + tiffHeader_.offset(), ifd_.read(pImage_ + tiffHeader_.offset(),
@ -184,9 +184,9 @@ namespace Exiv2 {
TiffThumbnail& TiffThumbnail::operator=(const TiffThumbnail& rhs) TiffThumbnail& TiffThumbnail::operator=(const TiffThumbnail& rhs)
{ {
char* pNewImage = 0; byte* pNewImage = 0;
if (rhs.pImage_ && rhs.size_ > 0) { if (rhs.pImage_ && rhs.size_ > 0) {
pNewImage = new char[rhs.size_]; pNewImage = new byte[rhs.size_];
memcpy(pNewImage, rhs.pImage_, rhs.size_); memcpy(pNewImage, rhs.pImage_, rhs.size_);
tiffHeader_.read(rhs.pImage_); tiffHeader_.read(rhs.pImage_);
ifd_.read(pNewImage + tiffHeader_.offset(), ifd_.read(pNewImage + tiffHeader_.offset(),
@ -200,7 +200,7 @@ namespace Exiv2 {
return *this; return *this;
} }
int TiffThumbnail::read(const char* buf, int TiffThumbnail::read(const byte* buf,
long len, long len,
const ExifData& exifData, const ExifData& exifData,
ByteOrder byteOrder) ByteOrder byteOrder)
@ -276,7 +276,7 @@ namespace Exiv2 {
ifd1.copy(img.pData_ + ifdOffset, tiffHeader.byteOrder(), ifdOffset); ifd1.copy(img.pData_ + ifdOffset, tiffHeader.byteOrder(), ifdOffset);
delete[] pImage_; delete[] pImage_;
pImage_ = new char[buflen]; pImage_ = new byte[buflen];
memcpy(pImage_, img.pData_, buflen); memcpy(pImage_, img.pData_, buflen);
size_ = buflen; size_ = buflen;
offset_ = minOffset; offset_ = minOffset;
@ -302,11 +302,12 @@ namespace Exiv2 {
int TiffThumbnail::write(const std::string& path) const int TiffThumbnail::write(const std::string& path) const
{ {
std::string name = path + extension(); std::string name = path + extension();
std::ofstream file(name.c_str(), std::ios::binary); FILE *ofp = fopen(name.c_str(), "wb");
if (!file) return -1; if (!ofp) return -1;
file.write(pImage_, size_); int rc = 0;
if (!file.good()) return 4; if (fwrite(pImage_, 1, size_, ofp) != (size_t)size_) rc = 4;
return 0; fclose(ofp);
return rc;
} // TiffThumbnail::write } // TiffThumbnail::write
void TiffThumbnail::update(ExifData& exifData) const void TiffThumbnail::update(ExifData& exifData) const
@ -338,7 +339,7 @@ namespace Exiv2 {
} // TiffThumbnail::update } // TiffThumbnail::update
long TiffThumbnail::copy(char* buf) const long TiffThumbnail::copy(byte* buf) const
{ {
long offset = ifd_.offset() + ifd_.size() + ifd_.dataSize(); long offset = ifd_.offset() + ifd_.size() + ifd_.dataSize();
long size = size_ - offset; long size = size_ - offset;
@ -402,16 +403,16 @@ namespace Exiv2 {
: offset_(rhs.offset_), size_(rhs.size_), pImage_(0) : offset_(rhs.offset_), size_(rhs.size_), pImage_(0)
{ {
if (rhs.pImage_ && rhs.size_ > 0) { if (rhs.pImage_ && rhs.size_ > 0) {
pImage_ = new char[rhs.size_]; pImage_ = new byte[rhs.size_];
memcpy(pImage_, rhs.pImage_, rhs.size_); memcpy(pImage_, rhs.pImage_, rhs.size_);
} }
} }
JpegThumbnail& JpegThumbnail::operator=(const JpegThumbnail& rhs) JpegThumbnail& JpegThumbnail::operator=(const JpegThumbnail& rhs)
{ {
char* pNewImage = 0; byte* pNewImage = 0;
if (rhs.pImage_ && rhs.size_ > 0) { if (rhs.pImage_ && rhs.size_ > 0) {
pNewImage = new char[rhs.size_]; pNewImage = new byte[rhs.size_];
memcpy(pNewImage, rhs.pImage_, rhs.size_); memcpy(pNewImage, rhs.pImage_, rhs.size_);
} }
offset_ = rhs.offset_; offset_ = rhs.offset_;
@ -421,7 +422,7 @@ namespace Exiv2 {
return *this; return *this;
} }
int JpegThumbnail::read(const char* buf, int JpegThumbnail::read(const byte* buf,
long len, long len,
const ExifData& exifData, const ExifData& exifData,
ByteOrder byteOrder) ByteOrder byteOrder)
@ -436,7 +437,7 @@ namespace Exiv2 {
long size = pos->toLong(); long size = pos->toLong();
if (len < offset + size) return 1; if (len < offset + size) return 1;
delete[] pImage_; delete[] pImage_;
pImage_ = new char[size]; pImage_ = new byte[size];
memcpy(pImage_, buf + offset, size); memcpy(pImage_, buf + offset, size);
size_ = size; size_ = size;
offset_ = offset; offset_ = offset;
@ -456,11 +457,12 @@ namespace Exiv2 {
int JpegThumbnail::write(const std::string& path) const int JpegThumbnail::write(const std::string& path) const
{ {
std::string name = path + extension(); std::string name = path + extension();
std::ofstream file(name.c_str(), std::ios::binary); FILE *ofp = fopen(name.c_str(), "wb");
if (!file) return -1; if (!ofp) return -1;
file.write(pImage_, size_); int rc = 0;
if (!file.good()) return 4; if (fwrite(pImage_, 1, size_, ofp) != (size_t)size_) rc = 4;
return 0; fclose(ofp);
return rc;
} // JpegThumbnail::write } // JpegThumbnail::write
void JpegThumbnail::update(ExifData& exifData) const void JpegThumbnail::update(ExifData& exifData) const
@ -487,7 +489,7 @@ namespace Exiv2 {
} // JpegThumbnail::update } // JpegThumbnail::update
long JpegThumbnail::copy(char* buf) const long JpegThumbnail::copy(byte* buf) const
{ {
memcpy(buf, pImage_, size_); memcpy(buf, pImage_, size_);
return size_; return size_;
@ -533,30 +535,25 @@ namespace Exiv2 {
int ExifData::read(const std::string& path) int ExifData::read(const std::string& path)
{ {
std::ifstream file(path.c_str(), std::ios::binary); Image* pImage = ImageFactory::instance().open(path);
if (!file) return -1; // Todo: if (!pImage) return -1;
Image* pImage = ImageFactory::instance().create(file);
if (pImage) { if (pImage) {
int rc = pImage->readExifData(file); int rc = pImage->readMetadata();
if (rc == 0) rc = read(pImage->exifData(), pImage->sizeExifData()); if (rc == 0 && pImage->sizeExifData() > 0 ) {
delete pImage; rc = read(pImage->exifData(), pImage->sizeExifData());
return rc;
} }
if (ExvFile::isThisType(file)) { delete pImage;
ExvFile exvFile;
int rc = exvFile.readExifData(file);
if (rc == 0) rc = read(exvFile.exifData(), exvFile.sizeExifData());
return rc; return rc;
} }
// We don't know this type of file // We don't know this type of file
return -2; return -2;
} }
int ExifData::read(const char* buf, long len) int ExifData::read(const byte* buf, long len)
{ {
// Copy the data buffer // Copy the data buffer
delete[] pData_; delete[] pData_;
pData_ = new char[len]; pData_ = new byte[len];
memcpy(pData_, buf, len); memcpy(pData_, buf, len);
size_ = len; size_ = len;
@ -581,8 +578,9 @@ namespace Exiv2 {
if (pos != exifIfd_.end() && make != ifd0_.end() && model != ifd0_.end()) { if (pos != exifIfd_.end() && make != ifd0_.end() && model != ifd0_.end()) {
MakerNoteFactory& mnf = MakerNoteFactory::instance(); MakerNoteFactory& mnf = MakerNoteFactory::instance();
// Todo: The conversion to string assumes that there is a \0 at the end // Todo: The conversion to string assumes that there is a \0 at the end
pMakerNote_ = mnf.create(make->data(), // Todo: How to avoid the cast (is that a MSVC thing?)
model->data(), pMakerNote_ = mnf.create(reinterpret_cast<const char*>(make->data()),
reinterpret_cast<const char*>(model->data()),
false, false,
pos->data(), pos->data(),
pos->size(), pos->size(),
@ -654,13 +652,15 @@ namespace Exiv2 {
int ExifData::erase(const std::string& path) const int ExifData::erase(const std::string& path) const
{ {
std::ifstream is(path.c_str(), std::ios::binary); Image* pImage = ImageFactory::instance().open(path);
if (!is) return -1;
Image* pImage = ImageFactory::instance().create(is);
is.close();
if (pImage == 0) return -2; if (pImage == 0) return -2;
int rc = pImage->eraseExifData(path); // Read all metadata then erase only Exif data
int rc = pImage->readMetadata();
if (rc == 0) {
pImage->clearExifData();
rc = pImage->writeMetadata();
}
delete pImage; delete pImage;
return rc; return rc;
} // ExifData::erase } // ExifData::erase
@ -670,23 +670,24 @@ namespace Exiv2 {
// Remove the Exif section from the file if there is no metadata // Remove the Exif section from the file if there is no metadata
if (count() == 0 && !pThumbnail_) return erase(path); if (count() == 0 && !pThumbnail_) return erase(path);
std::ifstream is(path.c_str(), std::ios::binary); Image* pImage = ImageFactory::instance().open(path);
if (!is) return -1;
Image* pImage = ImageFactory::instance().create(is);
is.close();
if (pImage == 0) return -2; if (pImage == 0) return -2;
DataBuf buf(size()); DataBuf buf(size());
long actualSize = copy(buf.pData_); long actualSize = copy(buf.pData_);
assert(actualSize <= buf.size_); assert(actualSize <= buf.size_);
// Read all metadata to preserve non-Exif data
int rc = pImage->readMetadata();
if (rc == 0) {
pImage->setExifData(buf.pData_, actualSize); pImage->setExifData(buf.pData_, actualSize);
int rc = pImage->writeExifData(path); rc = pImage->writeMetadata();
}
delete pImage; delete pImage;
return rc; return rc;
} // ExifData::write } // ExifData::write
long ExifData::copy(char* buf) long ExifData::copy(byte* buf)
{ {
long size = 0; long size = 0;
// If we can update the internal IFDs and the underlying data buffer // If we can update the internal IFDs and the underlying data buffer
@ -709,7 +710,7 @@ namespace Exiv2 {
return size; return size;
} }
long ExifData::copyFromMetadata(char* buf) long ExifData::copyFromMetadata(byte* buf)
{ {
// Build IFD0 // Build IFD0
Ifd ifd0(ifd0); Ifd ifd0(ifd0);
@ -873,9 +874,10 @@ namespace Exiv2 {
long actualSize = copy(buf.pData_); long actualSize = copy(buf.pData_);
assert(actualSize <= buf.size_); assert(actualSize <= buf.size_);
ExvFile exvFile; ExvImage exvImage(path, true);
exvFile.setExifData(buf.pData_, actualSize); if (!exvImage.good()) return -2;
return exvFile.writeExifData(path); exvImage.setExifData(buf.pData_, actualSize);
return exvImage.writeMetadata();
} // ExifData::writeExifData } // ExifData::writeExifData
void ExifData::add(Entries::const_iterator begin, void ExifData::add(Entries::const_iterator begin,

@ -21,7 +21,7 @@
/*! /*!
@file exif.hpp @file exif.hpp
@brief Encoding and decoding of Exif data @brief Encoding and decoding of Exif data
@version $Name: $ $Revision: 1.47 $ @version $Name: $ $Revision: 1.48 $
@author Andreas Huggel (ahu) @author Andreas Huggel (ahu)
<a href="mailto:ahuggel@gmx.net">ahuggel@gmx.net</a> <a href="mailto:ahuggel@gmx.net">ahuggel@gmx.net</a>
@date 09-Jan-04, ahu: created @date 09-Jan-04, ahu: created
@ -126,7 +126,7 @@ namespace Exiv2 {
@param byteOrder Applicable byte order (little or big endian). @param byteOrder Applicable byte order (little or big endian).
@return Number of characters written. @return Number of characters written.
*/ */
long copy(char* buf, ByteOrder byteOrder) const long copy(byte* buf, ByteOrder byteOrder) const
{ return pValue_ == 0 ? 0 : pValue_->copy(buf, byteOrder); } { return pValue_ == 0 ? 0 : pValue_->copy(buf, byteOrder); }
/*! /*!
@brief Return the key of the metadatum. The key is of the form @brief Return the key of the metadatum. The key is of the form
@ -274,7 +274,7 @@ namespace Exiv2 {
1 in case of inconsistent JPEG thumbnail Exif data<BR> 1 in case of inconsistent JPEG thumbnail Exif data<BR>
2 in case of inconsistent TIFF thumbnail Exif data 2 in case of inconsistent TIFF thumbnail Exif data
*/ */
virtual int read(const char* buf, virtual int read(const byte* buf,
long len, long len,
const ExifData& exifData, const ExifData& exifData,
ByteOrder byteOrder =littleEndian) =0; ByteOrder byteOrder =littleEndian) =0;
@ -319,7 +319,7 @@ namespace Exiv2 {
enough memory. Otherwise the call results in undefined enough memory. Otherwise the call results in undefined
behaviour. Return the number of characters written. behaviour. Return the number of characters written.
*/ */
virtual long copy(char* buf) const =0; virtual long copy(byte* buf) const =0;
/*! /*!
@brief Update the Exif data according to the actual thumbnail image. @brief Update the Exif data according to the actual thumbnail image.
@ -374,7 +374,7 @@ namespace Exiv2 {
//@{ //@{
//! Assignment operator. //! Assignment operator.
TiffThumbnail& operator=(const TiffThumbnail& rhs); TiffThumbnail& operator=(const TiffThumbnail& rhs);
int read(const char* buf, int read(const byte* buf,
long len, long len,
const ExifData& exifData, const ExifData& exifData,
ByteOrder byteOrder =littleEndian); ByteOrder byteOrder =littleEndian);
@ -386,7 +386,7 @@ namespace Exiv2 {
int write(const std::string& path) const; int write(const std::string& path) const;
const char* format() const; const char* format() const;
const char* extension() const; const char* extension() const;
long copy(char* buf) const; long copy(byte* buf) const;
void update(ExifData& exifData) const; void update(ExifData& exifData) const;
long offset() const; long offset() const;
long size() const; long size() const;
@ -398,7 +398,7 @@ namespace Exiv2 {
long offset_; // Original offset of the thumbnail data long offset_; // Original offset of the thumbnail data
// from the start of the TIFF header // from the start of the TIFF header
long size_; //!< Size of the image data long size_; //!< Size of the image data
char* pImage_; //!< Thumbnail image data byte* pImage_; //!< Thumbnail image data
TiffHeader tiffHeader_; //!< Thumbnail TIFF Header TiffHeader tiffHeader_; //!< Thumbnail TIFF Header
Ifd ifd_; //!< Thumbnail IFD (IFD1 of the Exif data) Ifd ifd_; //!< Thumbnail IFD (IFD1 of the Exif data)
@ -421,7 +421,7 @@ namespace Exiv2 {
//@{ //@{
//! Assignment operator. //! Assignment operator.
JpegThumbnail& operator=(const JpegThumbnail& rhs); JpegThumbnail& operator=(const JpegThumbnail& rhs);
int read(const char* buf, int read(const byte* buf,
long len, long len,
const ExifData& exifData, const ExifData& exifData,
ByteOrder byteOrder =littleEndian); ByteOrder byteOrder =littleEndian);
@ -433,7 +433,7 @@ namespace Exiv2 {
int write(const std::string& path) const; int write(const std::string& path) const;
const char* format() const; const char* format() const;
const char* extension() const; const char* extension() const;
long copy(char* buf) const; long copy(byte* buf) const;
void update(ExifData& exifData) const; void update(ExifData& exifData) const;
long offset() const; long offset() const;
long size() const; long size() const;
@ -445,7 +445,7 @@ namespace Exiv2 {
long offset_; // Original offset of the thumbnail data long offset_; // Original offset of the thumbnail data
// from the start of the TIFF header // from the start of the TIFF header
long size_; // Size of the image data long size_; // Size of the image data
char* pImage_; // Thumbnail image data byte* pImage_; // Thumbnail image data
}; // class JpegThumbnail }; // class JpegThumbnail
@ -543,13 +543,13 @@ namespace Exiv2 {
@param len Number of bytes in the data buffer @param len Number of bytes in the data buffer
@return 0 if successful. @return 0 if successful.
*/ */
int read(const char* buf, long len); int read(const byte* buf, long len);
/*! /*!
@brief Write the Exif data to file path. If an Exif data section @brief Write the Exif data to file path. If an Exif data section
already exists in the file, it is replaced. If there is no already exists in the file, it is replaced. If there is no
metadata and no thumbnail to write, the Exif data section is metadata and no thumbnail to write, the Exif data section is
deleted from the file. Otherwise, an Exif data section is deleted from the file. Otherwise, an Exif data section is
created. See copy(char* buf) for further details. created. See copy(byte* buf) for further details.
@return 0 if successful. @return 0 if successful.
*/ */
@ -585,7 +585,7 @@ namespace Exiv2 {
undefined behaviour. undefined behaviour.
@return Number of characters written to the buffer. @return Number of characters written to the buffer.
*/ */
long copy(char* buf); long copy(byte* buf);
/*! /*!
@brief Add all (IFD) entries in the range from iterator position begin @brief Add all (IFD) entries in the range from iterator position begin
to iterator position end to the Exif metadata. No duplicate to iterator position end to the Exif metadata. No duplicate
@ -782,7 +782,7 @@ namespace Exiv2 {
the Exif data with the metadata from the actual thumbnail image the Exif data with the metadata from the actual thumbnail image
(overriding existing metadata). (overriding existing metadata).
*/ */
long copyFromMetadata(char* buf); long copyFromMetadata(byte* buf);
//@} //@}
//! @name Accessors //! @name Accessors
@ -829,7 +829,7 @@ namespace Exiv2 {
Ifd ifd1_; Ifd ifd1_;
long size_; //!< Size of the Exif raw data in bytes long size_; //!< Size of the Exif raw data in bytes
char* pData_; //!< Exif raw data buffer byte* pData_; //!< Exif raw data buffer
/*! /*!
Can be set to false to indicate that non-intrusive writing is not Can be set to false to indicate that non-intrusive writing is not

@ -3,7 +3,7 @@
Abstract : Sample program showing how to set the Exif comment of an image Abstract : Sample program showing how to set the Exif comment of an image
File: exifcomment.cpp File: exifcomment.cpp
Version : $Name: $ $Revision: 1.2 $ Version : $Name: $ $Revision: 1.3 $
Author(s): Andreas Huggel (ahu) <ahuggel@gmx.net> Author(s): Andreas Huggel (ahu) <ahuggel@gmx.net>
History : 10-May-04, ahu: created History : 10-May-04, ahu: created
*/ */
@ -56,7 +56,8 @@ try {
std::string charset("ASCII\0\0\0", 8); std::string charset("ASCII\0\0\0", 8);
std::string comment("A comment added to the Exif metadata through Exiv2"); std::string comment("A comment added to the Exif metadata through Exiv2");
Exiv2::DataValue value; Exiv2::DataValue value;
value.read((charset + comment).data(), 8 + comment.size()); value.read(reinterpret_cast<const Exiv2::byte*>((charset + comment).data()),
8 + static_cast<long>(comment.size()));
// Set the Exif comment // Set the Exif comment
std::string key = "Image.UserInfo.UserComment"; std::string key = "Image.UserInfo.UserComment";

@ -20,7 +20,7 @@
*/ */
/* /*
File: fujimn.cpp File: fujimn.cpp
Version: $Name: $ $Revision: 1.7 $ Version: $Name: $ $Revision: 1.8 $
Author(s): Andreas Huggel (ahu) <ahuggel@gmx.net> Author(s): Andreas Huggel (ahu) <ahuggel@gmx.net>
History: 18-Feb-04, ahu: created History: 18-Feb-04, ahu: created
07-Mar-04, ahu: isolated as a separate component 07-Mar-04, ahu: isolated as a separate component
@ -31,7 +31,7 @@
*/ */
// ***************************************************************************** // *****************************************************************************
#include "rcsid.hpp" #include "rcsid.hpp"
EXIV2_RCSID("@(#) $Name: $ $Revision: 1.7 $ $RCSfile: fujimn.cpp,v $") EXIV2_RCSID("@(#) $Name: $ $Revision: 1.8 $ $RCSfile: fujimn.cpp,v $")
// ***************************************************************************** // *****************************************************************************
// included header files // included header files
@ -84,7 +84,7 @@ namespace Exiv2 {
absOffset_ = false; absOffset_ = false;
} }
int FujiMakerNote::readHeader(const char* buf, int FujiMakerNote::readHeader(const byte* buf,
long len, long len,
ByteOrder byteOrder) ByteOrder byteOrder)
{ {
@ -103,7 +103,8 @@ namespace Exiv2 {
int rc = 0; int rc = 0;
// Check the FUJIFILM prefix // Check the FUJIFILM prefix
if ( header_.size_ < 12 if ( header_.size_ < 12
|| std::string(header_.pData_, 8) != std::string("FUJIFILM", 8)) { || std::string(reinterpret_cast<char*>(header_.pData_), 8)
!= std::string("FUJIFILM", 8)) {
rc = 2; rc = 2;
} }
return rc; return rc;
@ -255,7 +256,7 @@ namespace Exiv2 {
// free functions // free functions
MakerNote* createFujiMakerNote(bool alloc, MakerNote* createFujiMakerNote(bool alloc,
const char* buf, const byte* buf,
long len, long len,
ByteOrder byteOrder, ByteOrder byteOrder,
long offset) long offset)

@ -24,7 +24,7 @@
in Appendix 4: Makernote of Fujifilm of the document in Appendix 4: Makernote of Fujifilm of the document
<a href="http://park2.wakwak.com/%7Etsuruzoh/Computer/Digicams/exif-e.html"> <a href="http://park2.wakwak.com/%7Etsuruzoh/Computer/Digicams/exif-e.html">
Exif file format</a> by TsuruZoh Tachibanaya Exif file format</a> by TsuruZoh Tachibanaya
@version $Name: $ $Revision: 1.5 $ @version $Name: $ $Revision: 1.6 $
@author Andreas Huggel (ahu) @author Andreas Huggel (ahu)
<a href="mailto:ahuggel@gmx.net">ahuggel@gmx.net</a> <a href="mailto:ahuggel@gmx.net">ahuggel@gmx.net</a>
@date 11-Feb-04, ahu: created @date 11-Feb-04, ahu: created
@ -73,7 +73,7 @@ namespace Exiv2 {
this copy and is responsible to delete it! this copy and is responsible to delete it!
*/ */
MakerNote* createFujiMakerNote(bool alloc, MakerNote* createFujiMakerNote(bool alloc,
const char* buf, const byte* buf,
long len, long len,
ByteOrder byteOrder, ByteOrder byteOrder,
long offset); long offset);
@ -97,7 +97,7 @@ namespace Exiv2 {
//! @name Manipulators //! @name Manipulators
//@{ //@{
int readHeader(const char* buf, int readHeader(const byte* buf,
long len, long len,
ByteOrder byteOrder); ByteOrder byteOrder);
//@} //@}

@ -109,7 +109,7 @@ char *alloca ();
GNU application programs can use a third alternative mode in which GNU application programs can use a third alternative mode in which
they can distinguish the relative order of options and other arguments. */ they can distinguish the relative order of options and other arguments. */
#include "getopt.h" #include "getopt_win32.h"
/* For communication from `getopt' to the caller. /* For communication from `getopt' to the caller.
When `getopt' finds an option that takes an argument, When `getopt' finds an option that takes an argument,

@ -16,7 +16,7 @@
int main() int main()
try { try {
long len = 76; long len = 76;
char buf[] Exiv2::byte buf[]
= { // No = { // No
0x00,0x04, 0x00,0x04,
// Tag Type Components Offset/Data // Tag Type Components Offset/Data
@ -45,7 +45,7 @@ try {
std::cout << "Tag not found!\n"; std::cout << "Tag not found!\n";
return 1; return 1;
} }
char data[] = { 'T', 'H', 'R', 'E', 'E', '\0' }; Exiv2::byte data[] = { 'T', 'H', 'R', 'E', 'E', '\0' };
std::cout << "Setting value of entry 3...\n"; std::cout << "Setting value of entry 3...\n";
pos->setValue(2, 6, data, 6); pos->setValue(2, 6, data, 6);

@ -20,14 +20,14 @@
*/ */
/* /*
File: ifd.cpp File: ifd.cpp
Version: $Name: $ $Revision: 1.23 $ Version: $Name: $ $Revision: 1.24 $
Author(s): Andreas Huggel (ahu) <ahuggel@gmx.net> Author(s): Andreas Huggel (ahu) <ahuggel@gmx.net>
History: 26-Jan-04, ahu: created History: 26-Jan-04, ahu: created
11-Feb-04, ahu: isolated as a component 11-Feb-04, ahu: isolated as a component
*/ */
// ***************************************************************************** // *****************************************************************************
#include "rcsid.hpp" #include "rcsid.hpp"
EXIV2_RCSID("@(#) $Name: $ $Revision: 1.23 $ $RCSfile: ifd.cpp,v $") EXIV2_RCSID("@(#) $Name: $ $Revision: 1.24 $ $RCSfile: ifd.cpp,v $")
// ***************************************************************************** // *****************************************************************************
// included header files // included header files
@ -68,7 +68,7 @@ namespace Exiv2 {
{ {
if (alloc_) { if (alloc_) {
if (rhs.pData_) { if (rhs.pData_) {
pData_ = new char[rhs.size()]; pData_ = new byte[rhs.size()];
memcpy(pData_, rhs.pData_, rhs.size()); memcpy(pData_, rhs.pData_, rhs.size());
} }
} }
@ -93,7 +93,7 @@ namespace Exiv2 {
delete[] pData_; delete[] pData_;
pData_ = 0; pData_ = 0;
if (rhs.pData_) { if (rhs.pData_) {
pData_ = new char[rhs.size()]; pData_ = new byte[rhs.size()];
memcpy(pData_, rhs.pData_, rhs.size()); memcpy(pData_, rhs.pData_, rhs.size());
} }
} }
@ -109,7 +109,7 @@ namespace Exiv2 {
assert(alloc_); assert(alloc_);
size_ = 4; size_ = 4;
delete[] pData_; delete[] pData_;
pData_ = new char[size_]; pData_ = new byte[size_];
} }
ul2Data(pData_, data, byteOrder); ul2Data(pData_, data, byteOrder);
// do not change size_ // do not change size_
@ -117,7 +117,7 @@ namespace Exiv2 {
count_ = 1; count_ = 1;
} }
void Entry::setValue(uint16 type, uint32 count, const char* buf, long len) void Entry::setValue(uint16 type, uint32 count, const byte* buf, long len)
{ {
long dataSize = count * TypeInfo::typeSize(TypeId(type)); long dataSize = count * TypeInfo::typeSize(TypeId(type));
// No minimum size requirement, but make sure the buffer can hold the data // No minimum size requirement, but make sure the buffer can hold the data
@ -126,7 +126,7 @@ namespace Exiv2 {
} }
if (alloc_) { if (alloc_) {
delete[] pData_; delete[] pData_;
pData_ = new char[len]; pData_ = new byte[len];
memset(pData_, 0x0, len); memset(pData_, 0x0, len);
memcpy(pData_, buf, dataSize); memcpy(pData_, buf, dataSize);
size_ = len; size_ = len;
@ -134,7 +134,7 @@ namespace Exiv2 {
else { else {
if (size_ == 0) { if (size_ == 0) {
// Set the data pointer of a virgin entry // Set the data pointer of a virgin entry
pData_ = const_cast<char*>(buf); pData_ = const_cast<byte*>(buf);
size_ = len; size_ = len;
} }
else { else {
@ -149,7 +149,7 @@ namespace Exiv2 {
count_ = count; count_ = count;
} // Entry::setValue } // Entry::setValue
const char* Entry::component(uint32 n) const const byte* Entry::component(uint32 n) const
{ {
if (n >= count()) return 0; if (n >= count()) return 0;
return data() + n * typeSize(); return data() + n * typeSize();
@ -159,7 +159,7 @@ namespace Exiv2 {
: alloc_(true), ifdId_(ifdId), offset_(0), dataOffset_(0), : alloc_(true), ifdId_(ifdId), offset_(0), dataOffset_(0),
pNext_(0), next_(0) pNext_(0), next_(0)
{ {
pNext_ = new char[4]; pNext_ = new byte[4];
memset(pNext_, 0x0, 4); memset(pNext_, 0x0, 4);
} }
@ -167,7 +167,7 @@ namespace Exiv2 {
: alloc_(true), ifdId_(ifdId), offset_(offset), dataOffset_(0), : alloc_(true), ifdId_(ifdId), offset_(offset), dataOffset_(0),
pNext_(0), next_(0) pNext_(0), next_(0)
{ {
pNext_ = new char[4]; pNext_ = new byte[4];
memset(pNext_, 0x0, 4); memset(pNext_, 0x0, 4);
} }
@ -176,7 +176,7 @@ namespace Exiv2 {
pNext_(0), next_(0) pNext_(0), next_(0)
{ {
if (alloc_) { if (alloc_) {
pNext_ = new char[4]; pNext_ = new byte[4];
memset(pNext_, 0x0, 4); memset(pNext_, 0x0, 4);
} }
} }
@ -192,12 +192,12 @@ namespace Exiv2 {
pNext_(rhs.pNext_), next_(rhs.next_) pNext_(rhs.pNext_), next_(rhs.next_)
{ {
if (alloc_ && rhs.pNext_) { if (alloc_ && rhs.pNext_) {
pNext_ = new char[4]; pNext_ = new byte[4];
memcpy(pNext_, rhs.pNext_, 4); memcpy(pNext_, rhs.pNext_, 4);
} }
} }
int Ifd::read(const char* buf, long len, ByteOrder byteOrder, long offset) int Ifd::read(const byte* buf, long len, ByteOrder byteOrder, long offset)
{ {
int rc = 0; int rc = 0;
long o = 0; long o = 0;
@ -242,7 +242,7 @@ namespace Exiv2 {
memcpy(pNext_, buf + o, 4); memcpy(pNext_, buf + o, 4);
} }
else { else {
pNext_ = const_cast<char*>(buf + o); pNext_ = const_cast<byte*>(buf + o);
} }
next_ = getULong(buf + o, byteOrder); next_ = getULong(buf + o, byteOrder);
} }
@ -356,7 +356,7 @@ namespace Exiv2 {
} }
int Ifd::readSubIfd( int Ifd::readSubIfd(
Ifd& dest, const char* buf, long len, ByteOrder byteOrder, uint16 tag Ifd& dest, const byte* buf, long len, ByteOrder byteOrder, uint16 tag
) const ) const
{ {
int rc = 0; int rc = 0;
@ -373,7 +373,7 @@ namespace Exiv2 {
return rc; return rc;
} // Ifd::readSubIfd } // Ifd::readSubIfd
long Ifd::copy(char* buf, ByteOrder byteOrder, long offset) long Ifd::copy(byte* buf, ByteOrder byteOrder, long offset)
{ {
if (offset != 0) offset_ = offset; if (offset != 0) offset_ = offset;
@ -508,7 +508,7 @@ namespace Exiv2 {
<< std::hex << std::right << i->offset(); << std::hex << std::right << i->offset();
} }
else { else {
unsigned char* data = (unsigned char*)i->data(); const byte* data = i->data();
for (int k = 0; k < i->size(); ++k) { for (int k = 0; k < i->size(); ++k) {
offset << std::setw(2) << std::setfill('0') << std::hex offset << std::setw(2) << std::setfill('0') << std::hex
<< (int)data[k] << " "; << (int)data[k] << " ";

@ -21,10 +21,10 @@
/*! /*!
@file ifd.hpp @file ifd.hpp
@brief Encoding and decoding of IFD (%Image File Directory) data @brief Encoding and decoding of IFD (%Image File Directory) data
@version $Name: $ $Revision: 1.19 $ @version $Name: $ $Revision: 1.20 $
@author Andreas Huggel (ahu) @author Andreas Huggel (ahu)
<a href="mailto:ahuggel@gmx.net">ahuggel@gmx.net</a> <a href="mailto:ahuggel@gmx.net">ahuggel@gmx.net</a>
@date 09-Jan-04, ahu: created @date 09-Jan-04, ahu: created<BR>
11-Feb-04, ahu: isolated as a component 11-Feb-04, ahu: isolated as a component
*/ */
#ifndef IFD_HPP_ #ifndef IFD_HPP_
@ -126,7 +126,7 @@ namespace Exiv2 {
@throw Error ("Size too small") if size is not large enough to hold @throw Error ("Size too small") if size is not large enough to hold
count components of the given type. count components of the given type.
*/ */
void setValue(uint16 type, uint32 count, const char* data, long size); void setValue(uint16 type, uint32 count, const byte* data, long size);
//@} //@}
//! @name Accessors //! @name Accessors
@ -161,12 +161,12 @@ namespace Exiv2 {
@brief Return a pointer to the data area. Do not attempt to write @brief Return a pointer to the data area. Do not attempt to write
to this pointer. to this pointer.
*/ */
const char* data() const { return pData_; } const byte* data() const { return pData_; }
/*! /*!
@brief Return a pointer to the n-th component, 0 if there is no @brief Return a pointer to the n-th component, 0 if there is no
n-th component. Do not attempt to write to this pointer. n-th component. Do not attempt to write to this pointer.
*/ */
const char* component(uint32 n) const; const byte* component(uint32 n) const;
//! Get the memory allocation mode //! Get the memory allocation mode
bool alloc() const { return alloc_; } bool alloc() const { return alloc_; }
//@} //@}
@ -198,7 +198,7 @@ namespace Exiv2 {
*/ */
long size_; long size_;
//! Pointer to the data buffer //! Pointer to the data buffer
char* pData_; byte* pData_;
}; // class Entry }; // class Entry
@ -323,7 +323,7 @@ namespace Exiv2 {
beyond the provided buffer. The IFD is cleared in this beyond the provided buffer. The IFD is cleared in this
case. case.
*/ */
int read(const char* buf, long len, ByteOrder byteOrder, long offset =0); int read(const byte* buf, long len, ByteOrder byteOrder, long offset =0);
/*! /*!
@brief Read a sub-IFD from the location pointed to by the directory entry @brief Read a sub-IFD from the location pointed to by the directory entry
with the given tag. with the given tag.
@ -344,7 +344,7 @@ namespace Exiv2 {
IFD. 0 is returned and no action is taken in this case. IFD. 0 is returned and no action is taken in this case.
*/ */
int readSubIfd( int readSubIfd(
Ifd& dest, const char* buf, long len, ByteOrder byteOrder, uint16 tag Ifd& dest, const byte* buf, long len, ByteOrder byteOrder, uint16 tag
) const; ) const;
/*! /*!
@brief Copy the IFD to a data array, update the offsets of the IFD and @brief Copy the IFD to a data array, update the offsets of the IFD and
@ -371,7 +371,7 @@ namespace Exiv2 {
original position, i.e., the offset of the IFD will be used. original position, i.e., the offset of the IFD will be used.
@return Returns the number of characters written. @return Returns the number of characters written.
*/ */
long copy(char* buf, ByteOrder byteOrder, long offset =0); long copy(byte* buf, ByteOrder byteOrder, long offset =0);
/*! /*!
@brief Reset the IFD. Delete all IFD entries from the class and put @brief Reset the IFD. Delete all IFD entries from the class and put
the object in a state where it can accept completely new the object in a state where it can accept completely new
@ -489,7 +489,7 @@ namespace Exiv2 {
//! Offset of the first data entry outside of the IFD directory //! Offset of the first data entry outside of the IFD directory
long dataOffset_; long dataOffset_;
//! Pointer to the offset of next IFD from the start of the TIFF header //! Pointer to the offset of next IFD from the start of the TIFF header
char* pNext_; byte* pNext_;
//! The offset of the next IFD as data value (always in sync with *pNext_) //! The offset of the next IFD as data value (always in sync with *pNext_)
uint32 next_; uint32 next_;

File diff suppressed because it is too large Load Diff

@ -21,11 +21,14 @@
/*! /*!
@file image.hpp @file image.hpp
@brief Class JpegImage to access JPEG images @brief Class JpegImage to access JPEG images
@version $Name: $ $Revision: 1.13 $ @version $Name: $ $Revision: 1.14 $
@author Andreas Huggel (ahu) @author Andreas Huggel (ahu)
<a href="mailto:ahuggel@gmx.net">ahuggel@gmx.net</a> <a href="mailto:ahuggel@gmx.net">ahuggel@gmx.net</a>
@date 09-Jan-04, ahu: created @author Brad Schick (brad)
11-Feb-04, ahu: isolated as a component <a href="mailto:schick@robotbattle.com">schick@robotbattle.com</a>
@date 09-Jan-04, ahu: created<BR>
11-Feb-04, ahu: isolated as a component<BR>
19-Jul-04, brad: revamped to be more flexible and support IPTC
*/ */
#ifndef IMAGE_HPP_ #ifndef IMAGE_HPP_
#define IMAGE_HPP_ #define IMAGE_HPP_
@ -36,13 +39,20 @@
// + standard includes // + standard includes
#include <string> #include <string>
#include <iosfwd>
#include <map> #include <map>
// ***************************************************************************** // *****************************************************************************
// namespace extensions // namespace extensions
namespace Exiv2 { namespace Exiv2 {
//! Type for function pointer that creates new Image instances
typedef class Image* (*NewInstanceFct)(const std::string& path, FILE* ifp);
//! Type for function pointer that checks image types
typedef bool (*IsThisTypeFct)(FILE* ifp, bool advance);
// ***************************************************************************** // *****************************************************************************
// class definitions // class definitions
@ -52,12 +62,10 @@ namespace Exiv2 {
class Image { class Image {
public: public:
//! Supported image formats //! Supported image formats
enum Type { none, jpeg }; enum Type { none, jpeg, exv };
//! @name Creators //! @name Creators
//@{ //@{
//! Default Constructor
Image() {}
//! Virtual Destructor //! Virtual Destructor
virtual ~Image() {} virtual ~Image() {}
//@} //@}
@ -65,99 +73,112 @@ namespace Exiv2 {
//! @name Manipulators //! @name Manipulators
//@{ //@{
/*! /*!
@brief Read the Exif data from the file path into the internal @brief Read metadata from assigned image file into internal
data buffer. buffers.
@param path Path to the file.
@return 0 if successful. @return 0 if successful.
*/ */
virtual int readExifData(const std::string& path) =0; virtual int readMetadata() =0;
/*! /*!
@brief Read the Exif data from the stream into the internal @brief Write metadata from internal buffers into to the image fle.
data buffer.
@param is Input stream to read from.
@return 0 if successful. @return 0 if successful.
*/ */
virtual int readExifData(std::istream& is) =0; virtual int writeMetadata() =0;
/*! /*!
@brief Read the Exif data from the buffer buf which has size bytes. @brief Set the Exif data. The data is copied into an internal data
@param buf Pointer to the data buffer. buffer and is not written until writeMetadata is called.
@param size Number of characters in the data buffer. @param buf Pointer to the new Exif data.
@param size Size in bytes of new Exif data.
*/ */
virtual void setExifData(const char* buf, long size) =0; virtual void setExifData(const byte* buf, long size) =0;
//@}
//! @name Accessors
//@{
//! Virtual copy construction
virtual Image* clone() const =0;
/*! /*!
@brief Determine if the content of the stream is an image of the type @brief Erase any buffered Exif data. Exif data is not removed
of this class. from the actual file until writeMetadata is called.
The advance flag determines if the read position in the stream is
moved (see below). This applies only if the image type matches and the
function returns true. If the image 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 is Input stream with the image.
@param advance Flag indicating whether the read position in the stream
should be advanced by the number of characters read to
analyse the image stream (true) or left at its original
position (false). This applies only if the image type
matches.
@return true if the type of the image matches that of this;<BR>
false if the type of the image does not match.
*/ */
virtual bool isThisType(std::istream& is, bool advance =false) const =0; virtual void clearExifData() =0;
/*! /*!
@brief Erase the Exif data from file path. @brief Set the Iptc data. The data is copied into an internal data
@param path Path to the file. buffer and is not written until writeMetadata is called.
@return 0 if successful. @param buf Pointer to the new Iptc data.
@param size Size in bytes of new Iptc data.
*/ */
virtual int eraseExifData(const std::string& path) const =0; virtual void setIptcData(const byte* buf, long size) =0;
/*! /*!
@brief Read from the image input stream is, erase Exif data from the @brief Erase any buffered Iptc data. Iptc data is not removed
image, if there is any, and write the resulting image to the from the actual file until writeMetadata is called.
output stream os.
@param os Output stream to write to (e.g., a temporary file).
@param is Input stream with the image from which the Exif data
should be erased.
@return 0 if successful.
*/ */
virtual int eraseExifData(std::ostream& os, std::istream& is) const =0; virtual void clearIptcData() =0;
/*! /*!
@brief Write the Exif data to file path. @brief Set the image comment. The data is copied into an internal data
@param path Path to the file. buffer and is not written until writeMetadata is called.
@return 0 if successful. @param comment String containing comment.
*/ */
virtual int writeExifData(const std::string& path) const =0; virtual void setComment(const std::string &comment) =0;
/*! /*!
@brief Read from the image input stream is, add Exif data to the @brief Erase any buffered comment. Comment is not removed
image, replacing existing Exif data, if there is any) and from the actual file until writeMetadata is called.
write the resulting image to the output stream os. */
@param os Output stream to write to (e.g., a temporary file). virtual void clearComment() =0;
@param is Input stream with the image to which the Exif data /*!
should be copied. @brief Copy all existing metadata from source %Image. The data is
copied into internal buffers and is not written until
writeMetadata is called.
@param image Metadata source. All metadata types are copied.
*/
virtual void setMetadata(const Image& image) =0;
/*!
@brief Erase all buffered metadata. Metadata is not removed
from the actual file until writeMetadata is called.
*/
virtual void clearMetadata() =0;
/*!
@brief Close associated image file but preserve buffered metadata.
@return 0 if successful. @return 0 if successful.
*/ */
virtual int writeExifData(std::ostream& os, std::istream& is) const =0; virtual int detach() =0;
//@}
//! @name Accessors
//@{
/*!
@brief Check if the %Image instance is valid. Use after object
construction.
@return true if the %Image is in a valid state.
*/
virtual bool good() const =0;
//! Return the size of the Exif data in bytes. //! Return the size of the Exif data in bytes.
virtual long sizeExifData() const =0; virtual long sizeExifData() const =0;
/*! /*!
@brief Return a read-only pointer to an Exif data buffer. Do not @brief Return a read-only pointer to an Exif data buffer. Do not
attempt to write to this buffer. attempt to write to this buffer.
*/ */
virtual const char* exifData() const =0; virtual const byte* exifData() const =0;
//! Return the size of the Iptc data in bytes.
virtual long sizeIptcData() const =0;
/*!
@brief Return a read-only pointer to an Iptc data buffer. Do not
attempt to write to this buffer.
*/
virtual const byte* iptcData() const =0;
/*!
@brief Return a read-only reference to the image comment.
Do not attempt to write to this string. May be an empty string.
*/
virtual std::string comment() const =0;
//@} //@}
protected: protected:
/*! //! @name Creators
@brief Assignment operator. Protected so that it can only be used //@{
by subclasses but not directly. //! Default Constructor
*/ Image() {}
Image& operator=(const Image& rhs) { return *this; } //@}
private:
// NOT Implemented
//! Copy constructor
Image(const Image& rhs);
//! Assignment operator
Image& operator=(const Image& rhs);
}; // class Image }; // class Image
@ -173,50 +194,63 @@ namespace Exiv2 {
//! @name Manipulators //! @name Manipulators
//@{ //@{
/*! /*!
@brief Get access to the image factory. @brief Register image type together with its function pointers.
Clients access the image factory exclusively through
this method.
*/
static ImageFactory& instance();
/*!
@brief Register an image prototype together with its type.
The image factory creates new images by cloning their associated The image factory creates new images calling their associated
prototypes. Additional images can be added by registering a prototype function pointer. Additional images can be added by registering
and its type. If called for a type which already exists in the list, new type and function pointers. If called for a type that already
the corresponding prototype is replaced. exists in the list, the corresponding prototype is replaced.
@param type Image type. @param type Image type.
@param pImage Pointer to the prototype. Ownership is transfered to the @param newInst Function pointer for creating image instances.
factory. @param isType Function pointer to test for matching image types.
*/ */
void registerImage(Image::Type type, Image* pImage); void registerImage(Image::Type type,
NewInstanceFct newInst,
IsThisTypeFct isType);
//@} //@}
//! @name Accessors //! @name Accessors
//@{ //@{
/*! /*!
@brief Create an %Image of the appropriate type, derived from the @brief Create an %Image of the appropriate type by opening the
contents of the stream is. specified file. File type is derived from the contents of the
@param is Image stream. The contents of the stream are tested to file.
determine the image type to create. @param path %Image file. The contents of the file are tested to
determine the image type to open. File extension is ignored.
@return A pointer that owns an %Image of the type derived from the @return A pointer that owns an %Image of the type derived from the
stream. If no image type could be determined, the pointer is 0. file. Caller must delete the returned object. If no image type
could be determined, the pointer is 0.
*/ */
Image* create(std::istream& is) const; Image* open(const std::string& path) const;
/*! /*!
@brief Create an %Image of the requested type. @brief Create an %Image of the requested type by creating a new
file. If the file already exists, it will be overwritten.
@param type Type of the image to be created. @param type Type of the image to be created.
@return A pointer that owns an %Image of the requested type. @param path %Image file. The contents of the file are tested to
If the image type is not supported, the pointer is 0. determine the image type to open. File extension is ignored.
@return A pointer that owns an %Image of the requested type. Caller
must delete the returned object. If the image type is not
supported, the pointer is 0.
*/ */
Image* create(Image::Type type) const; Image* create(Image::Type type, const std::string& path) const;
/*!
@brief Returns the image type of the provided file.
@param path %Image file. The contents of the file are tested to
determine the image type. File extension is ignored.
@return %Image type of Image::none if the type is not recognized.
*/
Image::Type getType(const std::string& path) const;
//@} //@}
/*!
@brief Get access to the image factory.
Clients access the image factory exclusively through
this method.
*/
static ImageFactory& instance();
private: private:
//! @name Creators //! @name Creators
//@{ //@{
@ -226,170 +260,362 @@ namespace Exiv2 {
ImageFactory(const ImageFactory& rhs); ImageFactory(const ImageFactory& rhs);
//@} //@}
//! Struct for storing image function pointers.
struct ImageFcts
{
NewInstanceFct newInstance;
IsThisTypeFct isThisType;
ImageFcts(NewInstanceFct newInst, IsThisTypeFct isType)
: newInstance(newInst), isThisType(isType) {}
ImageFcts() : newInstance(0), isThisType(0) {}
};
// DATA // DATA
//! Pointer to the one and only instance of this class. //! Pointer to the one and only instance of this class.
static ImageFactory* pInstance_; static ImageFactory* pInstance_;
//! Type used to store Image prototype classes //! Type used to store Image creation functions
typedef std::map<Image::Type, Image*> Registry; typedef std::map<Image::Type, ImageFcts> Registry;
//! List of image types and corresponding prototypes. //! List of image types and corresponding creation functions.
Registry registry_; Registry registry_;
}; // class ImageFactory }; // class ImageFactory
/*! /*!
@brief Helper class to access JPEG images @brief Abstract helper base class to access JPEG images
*/ */
class JpegImage : public Image { class JpegBase : public Image {
public: public:
//! @name Creators //! @name Creators
//@{ //@{
//! Default constructor //! Virtual destructor.
JpegImage(); virtual ~JpegBase();
//! Copy constructor
JpegImage(const JpegImage& rhs);
//! Destructor
~JpegImage();
//@} //@}
//! @name Manipulators //! @name Manipulators
//@{ //@{
//! Assignment operator
JpegImage& operator=(const JpegImage& rhs);
/*! /*!
@brief Read the Exif data from the file path into the internal @brief Read all metadata from the file into the internal
data buffer. data buffers. This method returns success even when
@param path Path to the file. no metadata is found in the image. Callers must therefore
check the size of indivdual metadata types before
accessing the data.
@return 0 if successful;<BR> @return 0 if successful;<BR>
-1 if the file cannot be opened; or<BR> 1 if reading from the file failed
the return code of readExifData(std::istream& is) (could be caused by invalid image);<BR>
if the call to this function fails. 2 if the file does not contain a valid image;<BR>
*/ */
int readExifData(const std::string& path); int readMetadata();
/*! /*!
@brief Read the Exif data from the stream into the internal @brief Write all buffered metadata to associated file. All existing
data buffer. metadata sections in the file are either replaced or erased.
@param is Input stream to read from. If data for a given metadata type has not been assigned,
then that metadata type will be erased from the file.
@return 0 if successful;<br>
1 if reading from the file failed;<BR>
2 if the associated file does not contain a valid image;<BR>
3 if the temporary output file can not be written to;<BR>
4 if renaming the temporary file fails;<br>
*/
int writeMetadata();
void setExifData(const byte* buf, long size);
void clearExifData();
void setIptcData(const byte* buf, long size);
void clearIptcData();
void setComment(const std::string &comment);
void clearComment();
void setMetadata(const Image& image);
void clearMetadata();
int detach();
//@}
//! @name Accessors
//@{
bool good() const;
long sizeExifData() const { return sizeExifData_; }
const byte* exifData() const { return pExifData_; }
long sizeIptcData() const { return sizeIptcData_; }
const byte* iptcData() const { return pIptcData_; }
std::string comment() const { return comment_; }
//@}
protected:
//! @name Creators
//@{
/*!
@brief Constructor for subclasses that have already opened a
file stream on the specified path.
@param path Full path to image file.
@param fp File pointer to open file.
*/
JpegBase(const std::string& path, FILE* fp);
/*!
@brief Constructor that can either open an existing image or create
a new image from scratch. If a new image is to be created, any
existing file is overwritten
@param path Full path to image file.
@param create Specifies if an existing file should be opened (false)
or if a new file should be created (true).
@param initData Data to initialize newly created files. Only used
when %create is true. Should contain the data for the smallest
valid image of the calling subclass.
@param dataSize Size of initData in bytes.
*/
JpegBase(const std::string& path, const bool create,
const byte initData[], const size_t dataSize);
//@}
//! @name Accessors
//@{
/*!
@brief Writes the image header (aka signature) to the file stream.
@param ofp File stream that the header is written to.
@return 0 if successful;<BR> @return 0 if successful;<BR>
1 if reading from the stream failed (consult the stream state 3 if the output file can not be written to;<BR>
for more information);<BR>
2 if the stream does not contain a JPEG image;<BR>
3 if no Exif APP1 segment was found after SOI at the
beginning of the input stream.
*/ */
int readExifData(std::istream& is); virtual int writeHeader(FILE* ofp) const =0;
/*! /*!
@brief Set the Exif data. The data is copied into the internal @brief Determine if the content of the stream is of the type of this
data buffer. class.
@param buf Pointer to the data buffer.
@param size Number of characters in the data buffer. 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 ifp Input file stream.
@param advance Flag indicating whether the read position in the stream
should be advanced by the number of characters read to
analyse the stream (true) or left at its original
position (false). This applies only if the type matches.
@return true if the stream data matches the type of this class;<BR>
false if the stream data does not match.
*/ */
void setExifData(const char* buf, long size); virtual bool isThisType(FILE* ifp, bool advance) const =0;
//@} //@}
// Constant Data
static const byte sos_; //!< JPEG SOS marker
static const byte eoi_; //!< JPEG EOI marker
static const byte app0_; //!< JPEG APP0 marker
static const byte app1_; //!< JPEG APP1 marker
static const byte app13_; //!< JPEG APP13 marker
static const byte com_; //!< JPEG Comment marker
static const char exifId_[]; //!< Exif identifier
static const char jfifId_[]; //!< JFIF identifier
static const char ps3Id_[]; //!< Photoshop marker
static const char bimId_[]; //!< Photoshop marker
static const uint16 iptc_; //!< Photoshop IPTC marker
private:
// DATA
FILE* fp_; //!< Image file (read write)
const std::string path_; //!< Image file name
long sizeExifData_; //!< Size of the Exif data buffer
byte* pExifData_; //!< Exif data buffer
long sizeIptcData_; //!< Size of the Iptc data buffer
byte* pIptcData_; //!< IPTC data buffer
std::string comment_; //!< JPEG comment
// METHODS
/*!
@brief Advances file stream to one byte past the next Jpeg marker
and returns the marker. This method should be called when the
file stream is positioned one byte past the end of a Jpeg segment.
@return the next Jpeg segment marker if successful;<BR>
-1 if a maker was not found before EOF;<BR>
*/
int advanceToMarker() const;
/*!
@brief Locates Photoshop formated IPTC data in a memory buffer.
Operates on raw data (rather than file streams) to simplify reuse.
@param pPSData Pointer to buffer containing entire payload of
Photoshop formated APP13 Jpeg segment.
@param sizePSData Size in bytes of pPSData.
@param record Output value that is set to the start of the IPTC
data block within pPSData (may not be null).
@param sizeHdr Output value that is set to the size of the header
within the IPTC data block pointed to by record (may not
be null).
@param sizeIptc Output value that is set to the size of the actual
IPTC data within the IPTC data block pointed to by record
(may not be null).
@return 0 if successful;<BR>
1 if the pPSData buffer does not contain valid data;<BR>
2 if no IPTC data was found in pPSData;<BR>
*/
int locateIptcData(const byte *pPSData,
long sizePSData,
const byte **record,
uint16 *const sizeHdr,
uint16 *const sizeIptc) const;
/*!
@brief Write to the associated file stream with the provided data.
@param initData Data to be written to the associated file
@param dataSize Size in bytes of data to be written
@return 0 if successful;<BR>
3 if the output file can not be written to;<BR>
*/
int initFile(const byte initData[], const size_t dataSize);
/*!
@brief Provides the main implementation of writeMetadata by
writing all buffered metadata to associated file.
@param os Output stream to write to (e.g., a temporary file).
@return 0 if successful;<br>
1 if reading from associated file failed;<BR>
2 if the file does not contain a valid image;<BR>
3 if the temporary output file can not be written to;<BR>
*/
int doWriteMetadata(FILE* ofp) const;
// NOT Implemented
//! Default constructor.
JpegBase();
//! Copy constructor
JpegBase(const JpegBase& rhs);
//! Assignment operator
JpegBase& operator=(const JpegBase& rhs);
}; // class JpegBase
/*!
@brief Helper class to access JPEG images
*/
class JpegImage : public JpegBase {
friend Image* newJpegInstance(const std::string& path, FILE* fp);
friend bool isJpegType(FILE* ifp, bool advance);
public:
//! @name Creators
//@{
/*!
@brief Constructor that can either open an existing Jpeg image or create
a new image from scratch. If a new image is to be created, any
existing file 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 path Full path to image file.
@param create Specifies if an existing file should be opened (false)
or if a new file should be created (true).
*/
JpegImage(const std::string& path, const bool create);
//! Destructor
~JpegImage() {}
//@}
protected:
//! @name Accessors //! @name Accessors
//@{ //@{
//! Virtual copy construction
Image* clone() const;
/*! /*!
@brief Determine if the content of the stream is a JPEG image. @brief Writes a Jpeg header (aka signature) to the file stream.
@param is Input stream to test. @param ofp File stream that the header is written to.
@return 0 if successful;<BR>
3 if the output file can not be written to;<BR>
*/
int writeHeader(FILE* ofp) const;
/*!
@brief Determine if the content of the file stream is a Jpeg image.
See base class for more details.
@param ifp Input file stream.
@param advance Flag indicating whether the read position in the stream @param advance Flag indicating whether the read position in the stream
should be advanced by the number of characters read to should be advanced by the number of characters read to
analyse the image stream (true) or left at its original analyse the stream (true) or left at its original
position (false). This applies only if the image type position (false). This applies only if the type matches.
matches. @return true if the file stream data matches a Jpeg image;<BR>
@return true if the input stream starts with the JPEG SOI marker. false if the stream data does not match.
The stream is not advanced in this case.<BR> */
false if the input stream does not begin with the JPEG SOI bool isThisType(FILE* ifp, bool advance) const;
marker. The stream is not advanced.<BR>
false if reading the first two bytes from the stream fails.
Consult the stream state for more information. In this case,
the stream may or may not have been advanced by 1 or 2
characters.
*/
bool isThisType(std::istream& is, bool advance) const;
/*!
@brief Erase the Exif data from file path, which must contain a JPEG
image. If an Exif APP1 section exists in the file, it is
erased.
@param path Path to the file.
@return 0 if successful;<br>
-1 if the input file cannot be opened;<br>
-3 if the temporary file cannot be opened;<br>
-4 if renaming the temporary file fails; or<br>
the return code of
eraseExifData(std::ostream& os, std::istream& is) const
if the call to this function fails.
*/
int eraseExifData(const std::string& path) const;
/*!
@brief Erase Exif data from the JPEG image is, write the resulting
image to the output stream os. If an Exif APP1 section exists
in the input file, it is erased.
@param os Output stream to write to (e.g., a temporary file).
@param is Input stream with the JPEG image from which the Exif data
should be erased.
@return 0 if successful;<BR>
1 if reading from the input stream failed (consult the stream
state for more information);<BR>
2 if the input stream does not contain a JPEG image;<BR>
3 if neither a JFIF APP0 segment nor a Exif APP1 segment was
found after SOI at the beginning of the input stream;<BR>
4 if writing to the output stream failed (consult the stream
state for more information).
*/
int eraseExifData(std::ostream& os, std::istream& is) const;
/*!
@brief Write the Exif data to file path, which must contain a JPEG
image. If an Exif APP1 section exists in the file, it is
replaced. Otherwise, an Exif data section is created.
@param path Path to the file.
@return 0 if successful;<br>
-1 if the input file cannot be opened;<br>
-3 if the temporary file cannot be opened;<br>
-4 if renaming the temporary file fails; or<br>
the return code of
writeExifData(std::ostream& os, std::istream& is) const
if the call to this function fails.
*/
int writeExifData(const std::string& path) const;
/*!
@brief Copy Exif data into the JPEG image is, write the resulting
image to the output stream os. If an Exif APP1 section exists
in the input file, it is replaced. Otherwise, an Exif data
section is created.
@param os Output stream to write to (e.g., a temporary file).
@param is Input stream with the JPEG image to which the Exif data
should be copied.
@return 0 if successful;<BR>
1 if reading from the input stream failed (consult the stream
state for more information);<BR>
2 if the input stream does not contain a JPEG image;<BR>
3 if neither a JFIF APP0 segment nor a Exif APP1 segment was
found after SOI at the beginning of the input stream;<BR>
4 if writing to the output stream failed (consult the stream
state for more information).
*/
int writeExifData(std::ostream& os, std::istream& is) const;
//! Return the size of the Exif data buffer
long sizeExifData() const { return sizeExifData_; }
//! Return a read-only pointer to the Exif data buffer
const char* exifData() const { return pExifData_; }
//@} //@}
private: private:
// DATA // Constant data
static const uint16 soi_; // SOI marker static const byte soi_; // SOI marker
static const uint16 app0_; // APP0 marker static const byte blank_[]; // Minimal Jpeg image
static const uint16 app1_; // APP1 marker
static const char exifId_[]; // Exif identifier
static const char jfifId_[]; // JFIF identifier
long sizeExifData_; // Size of the Exif data buffer //! @name Creators
char* pExifData_; // Exif data buffer //@{
/*!
@brief Constructor to be used when a Jpeg file has already
been opened. Meant for internal factory use.
@param path Full path to opened image file.
@param fp File pointer to open file.
*/
JpegImage(const std::string& path, FILE* fp) : JpegBase(path, fp) {}
//@}
// NOT Implemented
//! Default constructor
JpegImage();
//! Copy constructor
JpegImage(const JpegImage& rhs);
//! Assignment operator
JpegImage& operator=(const JpegImage& rhs);
}; // class JpegImage }; // class JpegImage
//! Helper class to access %Exiv2 files
class ExvImage : public JpegBase {
friend Image* newExvInstance(const std::string& path, FILE* fp);
friend bool isExvType(FILE* ifp, bool advance);
public:
//! @name Creators
//@{
/*!
@brief Constructor that can either open an existing Exv image or create
a new image from scratch. If a new image is to be created, any
existing file 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 path Full path to image file.
@param create Specifies if an existing file should be opened (false)
or if a new file should be created (true).
*/
ExvImage(const std::string& path, const bool create);
//! Destructor
~ExvImage() {}
//@}
protected:
//! @name Accessors
//@{
/*!
@brief Writes an Exv header (aka signature) to the file stream.
@param ofp File stream that the header is written to.
@return 0 if successful;<BR>
3 if the output file can not be written to;<BR>
*/
int writeHeader(FILE* ofp) const;
/*!
@brief Determine if the content of the file stream is a Exv image.
See base class for more details.
@param ifp Input file stream.
@param advance Flag indicating whether the read position in the stream
should be advanced by the number of characters read to
analyse the stream (true) or left at its original
position (false). This applies only if the type matches.
@return true if the file stream data matches a Exv image;<BR>
false if the stream data does not match.
*/
virtual bool isThisType(FILE* ifp, bool advance) const;
//@}
private:
// Constant data
static const char exiv2Id_[]; // Exv identifier
static const byte blank_[]; // Minimal exiv file
//! @name Creators
//@{
/*!
@brief Constructor to be used when an Exv file has already
been opened. Meant for internal factory use.
@param path Full path to opened image file.
@param fp File pointer to open file.
*/
ExvImage(const std::string& path, FILE* fp) : JpegBase(path, fp) {}
//@}
// NOT Implemented
//! Default constructor
ExvImage();
//! Copy constructor
ExvImage(const ExvImage& rhs);
//! Assignment operator
ExvImage& operator=(const ExvImage& rhs);
}; // class ExvImage
//! Helper class modelling the TIFF header structure. //! Helper class modelling the TIFF header structure.
class TiffHeader { class TiffHeader {
public: public:
@ -405,7 +631,7 @@ namespace Exiv2 {
//! @name Manipulators //! @name Manipulators
//@{ //@{
//! Read the TIFF header from a data buffer. Returns 0 if successful. //! Read the TIFF header from a data buffer. Returns 0 if successful.
int read(const char* buf); int read(const byte* buf);
//@} //@}
//! @name Accessors //! @name Accessors
@ -422,7 +648,7 @@ namespace Exiv2 {
@param buf The data buffer to write to. @param buf The data buffer to write to.
@return The number of bytes written. @return The number of bytes written.
*/ */
long copy(char* buf) const; long copy(byte* buf) const;
//! Return the size of the TIFF header in bytes. //! Return the size of the TIFF header in bytes.
long size() const { return 8; } long size() const { return 8; }
//! Return the byte order (little or big endian). //! Return the byte order (little or big endian).
@ -443,94 +669,6 @@ namespace Exiv2 {
uint32 offset_; uint32 offset_;
}; // class TiffHeader }; // class TiffHeader
//! Helper class to access %Exiv2 files
class ExvFile {
public:
//! @name Creators
//@{
//! Default Constructor
ExvFile();
//! Destructor
~ExvFile();
//! Copy constructor
ExvFile(const ExvFile& rhs);
//@}
//! @name Manipulators
//@{
//! Assignment operator
ExvFile& operator=(const ExvFile& rhs);
/*!
@brief Read the Exif data from the file path into the internal
data buffer.
@param path Path to the file.
@return 0 if successful.
*/
int readExifData(const std::string& path);
/*!
@brief Read the Exif data from the stream is into the internal
data buffer.
@param is Input stream to read from.
@return 0 if successful.
*/
int readExifData(std::istream& is);
/*!
@brief Read the Exif data from the buffer buf which has size bytes.
@param buf Pointer to the data buffer.
@param size Number of characters in the data buffer.
*/
void setExifData(const char* buf, long size);
//@}
//! @name Accessors
//@{
/*!
@brief Write the Exif data to file path.
@param path Path to the file.
@return 0 if successful.
*/
int writeExifData(const std::string& path) const;
//! Return the size of the Exif data in bytes.
long sizeExifData() const { return sizeExifData_; }
/*!
@brief Return a read-only pointer to an Exif data buffer. Do not
attempt to write to this buffer.
*/
const char* exifData() const { return pExifData_; }
//@}
/*!
@brief Determine if the content of the stream is of the type of this
class.
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 is Input stream.
@param advance Flag indicating whether the read position in the stream
should be advanced by the number of characters read to
analyse the stream (true) or left at its original
position (false). This applies only if the type matches.
@return true if the stream data matches the type of this class;<BR>
false if the stream data does not match.
*/
static bool isThisType(std::istream& is, bool advance =false);
private:
// DATA
static const uint16 app1_; // APP1 marker
static const char exifId_[]; // Exif identifier
long sizeExifData_; // Size of the Exif data buffer
char* pExifData_; // Exif data buffer
}; // class ExvFile
} // namespace Exiv2 } // namespace Exiv2
#endif // #ifndef IMAGE_HPP_ #endif // #ifndef IMAGE_HPP_

@ -0,0 +1,101 @@
#! /bin/sh
# Test driver for image file i/o
eraseTest()
{
src=$1
test=${src}.etst
good=${src}.egd
#setup
cp $src $test
#run tests
../src/metacopy $test $test
#check results
diffCheck $test $good
}
copyTest()
{
num=$1
src=$2
dst=$3
test=${dst}.c${num}tst
good=${dst}.c${num}gd
#setup
cp $dst $test
#run tests
../src/metacopy -a $src $test
#check results
diffCheck $test $good
}
iptcTest()
{
num=$1
src=$2
dst=$3
test=${dst}.i${num}tst
good=${dst}.i${num}gd
#setup
cp $dst $test
#run tests
../src/metacopy -ip $src $test
#check results
diffCheck $test $good
}
# Make sure to pass the test file first and the know good file second
diffCheck() {
test=$1
good=$2
#run diff and check results
diff -q --binary $test $good
if [ $? -ne 0 ]; then
let ++errors
else
rm $test
fi
}
test_files=("table.jpg" "smiley1.jpg" "smiley2.jpg")
let errors=0
cd ../test
echo
echo "Erase all tests..."
foreach i ($test_files); eraseTest $i; end
eraseTest "glider.exv" #extra test
echo "Copy all tests..."
let c=0
foreach src ($test_files)
let ++c
foreach dst ($test_files); copyTest $c $src $dst; end
end
echo "Copy iptc tests..."
let c=0
foreach src ($test_files)
let ++c
foreach dst ($test_files); iptcTest $c $src $dst; end
end
echo '---------------------------------------------------------'
if [ $errors -eq 0 ]; then
echo 'All test cases passed'
else
echo $errors 'test case(s) failed!'
fi

@ -20,13 +20,13 @@
*/ */
/* /*
File: makernote.cpp File: makernote.cpp
Version: $Name: $ $Revision: 1.22 $ Version: $Name: $ $Revision: 1.23 $
Author(s): Andreas Huggel (ahu) <ahuggel@gmx.net> Author(s): Andreas Huggel (ahu) <ahuggel@gmx.net>
History: 18-Feb-04, ahu: created History: 18-Feb-04, ahu: created
*/ */
// ***************************************************************************** // *****************************************************************************
#include "rcsid.hpp" #include "rcsid.hpp"
EXIV2_RCSID("@(#) $Name: $ $Revision: 1.22 $ $RCSfile: makernote.cpp,v $") EXIV2_RCSID("@(#) $Name: $ $Revision: 1.23 $ $RCSfile: makernote.cpp,v $")
// Define DEBUG_* to output debug information to std::cerr // Define DEBUG_* to output debug information to std::cerr
#undef DEBUG_MAKERNOTE #undef DEBUG_MAKERNOTE
@ -165,7 +165,7 @@ namespace Exiv2 {
{ {
} }
int IfdMakerNote::read(const char* buf, int IfdMakerNote::read(const byte* buf,
long len, long len,
ByteOrder byteOrder, ByteOrder byteOrder,
long offset) long offset)
@ -206,7 +206,7 @@ namespace Exiv2 {
return rc; return rc;
} // IfdMakerNote::read } // IfdMakerNote::read
long IfdMakerNote::copy(char* buf, ByteOrder byteOrder, long offset) long IfdMakerNote::copy(byte* buf, ByteOrder byteOrder, long offset)
{ {
// Remember the new offset // Remember the new offset
offset_ = offset; offset_ = offset;
@ -222,7 +222,7 @@ namespace Exiv2 {
return len; return len;
} // IfdMakerNote::copy } // IfdMakerNote::copy
int IfdMakerNote::readHeader(const char* buf, int IfdMakerNote::readHeader(const byte* buf,
long len, long len,
ByteOrder byteOrder) ByteOrder byteOrder)
{ {
@ -236,7 +236,7 @@ namespace Exiv2 {
return 0; return 0;
} }
long IfdMakerNote::copyHeader(char* buf) const long IfdMakerNote::copyHeader(byte* buf) const
{ {
if (header_.size_ != 0) memcpy(buf, header_.pData_, header_.size_); if (header_.size_ != 0) memcpy(buf, header_.pData_, header_.size_);
return header_.size_; return header_.size_;
@ -309,7 +309,7 @@ namespace Exiv2 {
MakerNote* MakerNoteFactory::create(const std::string& make, MakerNote* MakerNoteFactory::create(const std::string& make,
const std::string& model, const std::string& model,
bool alloc, bool alloc,
const char* buf, const byte* buf,
long len, long len,
ByteOrder byteOrder, ByteOrder byteOrder,
long offset) const long offset) const
@ -386,7 +386,7 @@ namespace Exiv2 {
#ifdef DEBUG_REGISTRY #ifdef DEBUG_REGISTRY
std::cerr << "Exact match (score: " << key.size() + 2 << ")\n"; std::cerr << "Exact match (score: " << key.size() + 2 << ")\n";
#endif #endif
return key.size() + 2; return static_cast<int>(key.size()) + 2;
} }
std::string uKey = key; std::string uKey = key;
std::string uReg = regEntry; std::string uReg = regEntry;
@ -448,7 +448,7 @@ namespace Exiv2 {
} }
if (found) { if (found) {
count += ss.size(); count += static_cast<int>(ss.size());
} }
else { else {
#ifdef DEBUG_REGISTRY #ifdef DEBUG_REGISTRY

@ -22,7 +22,7 @@
@file makernote.hpp @file makernote.hpp
@brief Contains the Exif %MakerNote interface, IFD %MakerNote and a @brief Contains the Exif %MakerNote interface, IFD %MakerNote and a
MakerNote factory MakerNote factory
@version $Name: $ $Revision: 1.20 $ @version $Name: $ $Revision: 1.21 $
@author Andreas Huggel (ahu) @author Andreas Huggel (ahu)
<a href="mailto:ahuggel@gmx.net">ahuggel@gmx.net</a> <a href="mailto:ahuggel@gmx.net">ahuggel@gmx.net</a>
@date 18-Feb-04, ahu: created @date 18-Feb-04, ahu: created
@ -53,7 +53,7 @@ namespace Exiv2 {
// type definitions // type definitions
//! Type for a pointer to a function creating a makernote //! Type for a pointer to a function creating a makernote
typedef MakerNote* (*CreateFct)(bool, const char*, long, ByteOrder, long); typedef MakerNote* (*CreateFct)(bool, const byte*, long, ByteOrder, long);
// ***************************************************************************** // *****************************************************************************
// class definitions // class definitions
@ -137,7 +137,7 @@ namespace Exiv2 {
start of the TIFF header) and encoded in byte order byteOrder. start of the TIFF header) and encoded in byte order byteOrder.
Return 0 if successful. Return 0 if successful.
*/ */
virtual int read(const char* buf, virtual int read(const byte* buf,
long len, long len,
ByteOrder byteOrder, ByteOrder byteOrder,
long offset) =0; long offset) =0;
@ -147,7 +147,7 @@ namespace Exiv2 {
in byte order byteOrder. Update internal offsets if necessary. in byte order byteOrder. Update internal offsets if necessary.
Return the number of bytes written. Return the number of bytes written.
*/ */
virtual long copy(char* buf, ByteOrder byteOrder, long offset) =0; virtual long copy(byte* buf, ByteOrder byteOrder, long offset) =0;
/*! /*!
@brief Add the entry to the makernote. No duplicate-check is performed, @brief Add the entry to the makernote. No duplicate-check is performed,
i.e., it is possible to add multiple entries with the same tag. i.e., it is possible to add multiple entries with the same tag.
@ -279,7 +279,7 @@ namespace Exiv2 {
//! @name Manipulators //! @name Manipulators
//@{ //@{
virtual int read(const char* buf, virtual int read(const byte* buf,
long len, long len,
ByteOrder byteOrder, ByteOrder byteOrder,
long offset); long offset);
@ -291,10 +291,10 @@ namespace Exiv2 {
@note The default implementation does nothing, assuming there is no @note The default implementation does nothing, assuming there is no
header header
*/ */
virtual int readHeader(const char* buf, virtual int readHeader(const byte* buf,
long len, long len,
ByteOrder byteOrder); ByteOrder byteOrder);
virtual long copy(char* buf, ByteOrder byteOrder, long offset); virtual long copy(byte* buf, ByteOrder byteOrder, long offset);
void add(const Entry& entry) { ifd_.add(entry); } void add(const Entry& entry) { ifd_.add(entry); }
Entries::iterator begin() { return ifd_.begin(); } Entries::iterator begin() { return ifd_.begin(); }
Entries::iterator end() { return ifd_.end(); } Entries::iterator end() { return ifd_.end(); }
@ -319,7 +319,7 @@ namespace Exiv2 {
number of characters written. number of characters written.
@note The default implementation copies the header_ buffer. @note The default implementation copies the header_ buffer.
*/ */
virtual long copyHeader(char* buf) const; virtual long copyHeader(byte* buf) const;
/*! /*!
@brief Return the size of the makernote header in bytes. @brief Return the size of the makernote header in bytes.
@note The default implementation returns the size of the header_ @note The default implementation returns the size of the header_
@ -445,7 +445,7 @@ namespace Exiv2 {
MakerNote* create(const std::string& make, MakerNote* create(const std::string& make,
const std::string& model, const std::string& model,
bool alloc, bool alloc,
const char* buf, const byte* buf,
long len, long len,
ByteOrder byteOrder, ByteOrder byteOrder,
long offset) const; long offset) const;

@ -0,0 +1,193 @@
// ***************************************************************** -*- C++ -*-
/*
* Copyright (C) 2004 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.
*/
/*
Abstract : Tester application for image file handling
File : metacopy.cpp
Version : $Name: $ $Revision: 1.1 $
Author(s): Brad Schick (brad) <schick@robotbattle.com>
History : 13-Jul-04, brad: created
*/
// *****************************************************************************
// included header files
#include "exif.hpp"
#include "types.hpp"
#include "metacopy.hpp"
#include <iostream>
#include <fstream>
// *****************************************************************************
// Main
int main(int argc, char* const argv[])
{
try {
// Handle command line arguments
Params params;
if (params.getopt(argc, argv)) {
params.usage();
return 1;
}
if (params.help_) {
params.help();
return 2;
}
Exiv2::Image* readImg = Exiv2::ImageFactory::instance().open(params.read_);
if (!readImg) {
std::cerr << params.progname() <<
": Could not read file (" << params.read_ << ")\n";
return 4;
}
if (readImg->readMetadata()) {
std::cerr << params.progname() <<
": Could not read metadata from (" << params.read_ << ")\n";
return 5;
}
readImg->detach();
Exiv2::Image* writeImg = Exiv2::ImageFactory::instance().open(params.write_);
if (!writeImg) {
std::cerr << params.progname() <<
": Could not read file (" << params.write_ << ")\n";
return 6;
}
if (params.preserve_) {
if (writeImg->readMetadata()) {
std::cerr << params.progname() <<
": Could not read metadata from (" << params.write_ << ")\n";
return 7;
}
}
if (params.iptc_) {
writeImg->setIptcData(readImg->iptcData(), readImg->sizeIptcData());
}
if (params.exif_) {
writeImg->setExifData(readImg->exifData(), readImg->sizeExifData());
}
if (params.comment_) {
writeImg->setComment(readImg->comment());
}
if (writeImg->writeMetadata()) {
std::cerr << params.progname() <<
": Could not write metadata to (" << params.write_ << ")\n";
return 8;
}
delete readImg;
delete writeImg;
return 0;
}
catch (Exiv2::Error& e) {
std::cerr << "Caught Exiv2 exception '" << e << "'\n";
return 10;
}
}
int Params::option(int opt, const std::string& optarg, int optopt)
{
int rc = 0;
switch (opt) {
case 'h': help_ = true; break;
case 'i': iptc_ = true; break;
case 'e': exif_ = true; break;
case 'c': comment_ = true; break;
case 'p': preserve_ = true; break;
case 'a':
iptc_ =true;
exif_ =true;
comment_ =true;
break;
case ':':
std::cerr << progname() << ": Option -" << static_cast<char>(optopt)
<< " requires an argument\n";
rc = 1;
break;
case '?':
std::cerr << progname() << ": Unrecognized option -"
<< static_cast<char>(optopt) << "\n";
rc = 1;
break;
default:
std::cerr << progname()
<< ": getopt returned unexpected character code "
<< std::hex << opt << "\n";
rc = 1;
break;
}
return rc;
}
int Params::nonoption(const std::string& argv)
{
if (!write_.empty()) {
std::cerr << progname() << ": Unexpected extra argument (" << argv << ")\n";
return 1;
}
if (first_) read_ = argv;
else write_ = argv;
first_ = false;
return 0;
}
int Params::getopt(int argc, char* const argv[])
{
int rc = Util::Getopt::getopt(argc, argv, optstring_);
// Further consistency checks
if (help_==false) {
if (rc==0 && read_.empty() ) {
std::cerr << progname() << ": Read and write files must be specified\n";
rc = 1;
}
if (rc==0 && write_.empty() ) {
std::cerr << progname() << ": Write file must be specified\n";
rc = 1;
}
if (preserve_ && iptc_ && exif_ && comment_ ) {
std::cerr << progname() << ": Option -p has no effect when all metadata types are specified.\n";
rc = 1;
}
}
return rc;
} // Params::getopt
void Params::usage(std::ostream& os) const
{
os << "\nReads and writes raw metadata. Use -h option for help.\n"
<< "Usage: " << progname()
<< " [-iecaph] readfile writefile\n";
}
void Params::help(std::ostream& os) const
{
usage(os);
os << "\nOptions:\n"
<< " -i Read Iptc data from readfile and write to writefile.\n"
<< " -e Read Exif data from readfile and write to writefile.\n"
<< " -c Read Jpeg comment from readfile and write to writefile.\n"
<< " -a Read all metadata from readfile and write to writefile.\n"
<< " -p Preserve existing metadata in writefile if not replaced.\n"
<< " -h Display this help and exit.\n\n";
} // Params::help

@ -0,0 +1,86 @@
// ***************************************************************** -*- C++ -*-
/*
* Copyright (C) 2004 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 metacopy.hpp
@brief Defines class Params, used for the command line handling
@version $Name: $ $Revision: 1.1 $
@author Brad Schick (brad) <schick@robotbattle.com>
@date 13-Jul-04, brad: created
*/
#ifndef METACOPY_HPP_
#define METACOPY_HPP_
#include "utils.hpp"
class Params : public Util::Getopt {
private:
std::string optstring_;
bool first_;
public:
bool help_; //!< Help option flag.
bool iptc_; //!< IPTC option flag.
bool exif_; //!< Exif option flag.
bool comment_; //!< JPEG comment option flag.
bool preserve_; //!< Preserve existing metadata option flag.
std::string read_; //!< Source file
std::string write_; //!< Destination file
public:
/*!
@brief Default constructor. Note that optstring_ is initialized here.
*/
Params() : optstring_(":iecaph"),
first_(true),
help_(false),
iptc_(false),
exif_(false),
comment_(false),
preserve_(false)
{}
/*!
@brief Call Getopt::getopt() with optstring, to initiate command line
argument parsing, perform consistency checks after all command line
arguments are parsed.
@param argc Argument count as passed to main() on program invocation.
@param argv Argument array as passed to main() on program invocation.
@return 0 if successful, >0 in case of errors.
*/
int getopt(int argc, char* const argv[]);
//! Handle options and their arguments.
virtual int option(int opt, const std::string& optarg, int optopt);
//! Handle non-option parameters.
virtual int nonoption(const std::string& argv);
//! Print a minimal usage note to an output stream.
void usage(std::ostream& os =std::cout) const;
//! Print further usage explanations to an output stream.
void help(std::ostream& os =std::cout) const;
}; // class Params
#endif // METACOPY_HPP_

@ -20,14 +20,14 @@
*/ */
/* /*
File: nikon1mn.cpp File: nikon1mn.cpp
Version: $Name: $ $Revision: 1.2 $ Version: $Name: $ $Revision: 1.3 $
Author(s): Andreas Huggel (ahu) <ahuggel@gmx.net> Author(s): Andreas Huggel (ahu) <ahuggel@gmx.net>
History: 17-May-04, ahu: created History: 17-May-04, ahu: created
25-May-04, ahu: combined all Nikon formats in one component 25-May-04, ahu: combined all Nikon formats in one component
*/ */
// ***************************************************************************** // *****************************************************************************
#include "rcsid.hpp" #include "rcsid.hpp"
EXIV2_RCSID("@(#) $Name: $ $Revision: 1.2 $ $RCSfile: nikonmn.cpp,v $") EXIV2_RCSID("@(#) $Name: $ $Revision: 1.3 $ $RCSfile: nikonmn.cpp,v $")
// ***************************************************************************** // *****************************************************************************
// included header files // included header files
@ -202,7 +202,7 @@ namespace Exiv2 {
{ {
} }
int Nikon2MakerNote::readHeader(const char* buf, int Nikon2MakerNote::readHeader(const byte* buf,
long len, long len,
ByteOrder byteOrder) ByteOrder byteOrder)
{ {
@ -219,7 +219,8 @@ namespace Exiv2 {
int rc = 0; int rc = 0;
// Check the Nikon prefix // Check the Nikon prefix
if ( header_.size_ < 8 if ( header_.size_ < 8
|| std::string(header_.pData_, 6) != std::string("Nikon\0", 6)) { || std::string(reinterpret_cast<char*>(header_.pData_), 6)
!= std::string("Nikon\0", 6)) {
rc = 2; rc = 2;
} }
return rc; return rc;
@ -387,7 +388,7 @@ namespace Exiv2 {
absOffset_ = false; absOffset_ = false;
} }
int Nikon3MakerNote::readHeader(const char* buf, int Nikon3MakerNote::readHeader(const byte* buf,
long len, long len,
ByteOrder byteOrder) ByteOrder byteOrder)
{ {
@ -407,7 +408,8 @@ namespace Exiv2 {
int rc = 0; int rc = 0;
// Check the Nikon prefix // Check the Nikon prefix
if ( header_.size_ < 18 if ( header_.size_ < 18
|| std::string(header_.pData_, 6) != std::string("Nikon\0", 6)) { || std::string(reinterpret_cast<char*>(header_.pData_), 6)
!= std::string("Nikon\0", 6)) {
rc = 2; rc = 2;
} }
return rc; return rc;
@ -521,13 +523,14 @@ namespace Exiv2 {
// free functions // free functions
MakerNote* createNikonMakerNote(bool alloc, MakerNote* createNikonMakerNote(bool alloc,
const char* buf, const byte* buf,
long len, long len,
ByteOrder byteOrder, ByteOrder byteOrder,
long offset) long offset)
{ {
// If there is no "Nikon" string it must be Nikon1 format // If there is no "Nikon" string it must be Nikon1 format
if (len < 6 || std::string(buf, 6) != std::string("Nikon\0", 6)) { if (len < 6 || std::string(reinterpret_cast<const char*>(buf), 6)
!= std::string("Nikon\0", 6)) {
return new Nikon1MakerNote(alloc); return new Nikon1MakerNote(alloc);
} }
// If the "Nikon" string is not followed by a TIFF header, we assume // If the "Nikon" string is not followed by a TIFF header, we assume

@ -28,10 +28,10 @@
<a href="http://park2.wakwak.com/%7Etsuruzoh/Computer/Digicams/exif-e.html"> <a href="http://park2.wakwak.com/%7Etsuruzoh/Computer/Digicams/exif-e.html">
Exif file format</a> by TsuruZoh Tachibanaya.<BR> Exif file format</a> by TsuruZoh Tachibanaya.<BR>
Format 3: "EXIFutils Field Reference Guide". Format 3: "EXIFutils Field Reference Guide".
@version $Name: $ $Revision: 1.2 $ @version $Name: $ $Revision: 1.3 $
@author Andreas Huggel (ahu) @author Andreas Huggel (ahu)
<a href="mailto:ahuggel@gmx.net">ahuggel@gmx.net</a> <a href="mailto:ahuggel@gmx.net">ahuggel@gmx.net</a>
@date 17-May-04, ahu: created @date 17-May-04, ahu: created<BR>
25-May-04, ahu: combined all Nikon formats in one component 25-May-04, ahu: combined all Nikon formats in one component
*/ */
#ifndef NIKONMN_HPP_ #ifndef NIKONMN_HPP_
@ -78,7 +78,7 @@ namespace Exiv2 {
this copy and is responsible to delete it! this copy and is responsible to delete it!
*/ */
MakerNote* createNikonMakerNote(bool alloc, MakerNote* createNikonMakerNote(bool alloc,
const char* buf, const byte* buf,
long len, long len,
ByteOrder byteOrder, ByteOrder byteOrder,
long offset); long offset);
@ -173,7 +173,7 @@ namespace Exiv2 {
//! @name Manipulators //! @name Manipulators
//@{ //@{
int readHeader(const char* buf, int readHeader(const byte* buf,
long len, long len,
ByteOrder byteOrder); ByteOrder byteOrder);
//@} //@}
@ -227,7 +227,7 @@ namespace Exiv2 {
//! @name Manipulators //! @name Manipulators
//@{ //@{
int readHeader(const char* buf, int readHeader(const byte* buf,
long len, long len,
ByteOrder byteOrder); ByteOrder byteOrder);
//@} //@}

@ -20,7 +20,7 @@
*/ */
/* /*
File: sigmamn.cpp File: sigmamn.cpp
Version: $Name: $ $Revision: 1.6 $ Version: $Name: $ $Revision: 1.7 $
Author(s): Andreas Huggel (ahu) <ahuggel@gmx.net> Author(s): Andreas Huggel (ahu) <ahuggel@gmx.net>
History: 02-Apr-04, ahu: created History: 02-Apr-04, ahu: created
Credits: Sigma and Foveon MakerNote implemented according to the specification Credits: Sigma and Foveon MakerNote implemented according to the specification
@ -29,7 +29,7 @@
*/ */
// ***************************************************************************** // *****************************************************************************
#include "rcsid.hpp" #include "rcsid.hpp"
EXIV2_RCSID("@(#) $Name: $ $Revision: 1.6 $ $RCSfile: sigmamn.cpp,v $") EXIV2_RCSID("@(#) $Name: $ $Revision: 1.7 $ $RCSfile: sigmamn.cpp,v $")
// ***************************************************************************** // *****************************************************************************
// included header files // included header files
@ -87,7 +87,7 @@ namespace Exiv2 {
{ {
} }
int SigmaMakerNote::readHeader(const char* buf, int SigmaMakerNote::readHeader(const byte* buf,
long len, long len,
ByteOrder byteOrder) ByteOrder byteOrder)
{ {
@ -108,8 +108,10 @@ namespace Exiv2 {
int rc = 0; int rc = 0;
// Check the SIGMA or FOVEON prefix // Check the SIGMA or FOVEON prefix
if ( header_.size_ < 10 if ( header_.size_ < 10
|| std::string(header_.pData_, 8) != std::string("SIGMA\0\0\0", 8) || std::string(reinterpret_cast<char*>(header_.pData_), 8)
&& std::string(header_.pData_, 8) != std::string("FOVEON\0\0", 8)) { != std::string("SIGMA\0\0\0", 8)
&& std::string(reinterpret_cast<char*>(header_.pData_), 8)
!= std::string("FOVEON\0\0", 8)) {
rc = 2; rc = 2;
} }
return rc; return rc;
@ -188,7 +190,7 @@ namespace Exiv2 {
// free functions // free functions
MakerNote* createSigmaMakerNote(bool alloc, MakerNote* createSigmaMakerNote(bool alloc,
const char* buf, const byte* buf,
long len, long len,
ByteOrder byteOrder, ByteOrder byteOrder,
long offset) long offset)

@ -23,7 +23,7 @@
@brief Sigma and Foveon MakerNote implemented according to the specification @brief Sigma and Foveon MakerNote implemented according to the specification
<a href="http://www.x3f.info/technotes/FileDocs/MakerNoteDoc.html"> <a href="http://www.x3f.info/technotes/FileDocs/MakerNoteDoc.html">
SIGMA and FOVEON EXIF MakerNote Documentation</a> by Foveon. SIGMA and FOVEON EXIF MakerNote Documentation</a> by Foveon.
@version $Name: $ $Revision: 1.5 $ @version $Name: $ $Revision: 1.6 $
@author Andreas Huggel (ahu) @author Andreas Huggel (ahu)
<a href="mailto:ahuggel@gmx.net">ahuggel@gmx.net</a> <a href="mailto:ahuggel@gmx.net">ahuggel@gmx.net</a>
@date 02-Apr-04, ahu: created @date 02-Apr-04, ahu: created
@ -72,7 +72,7 @@ namespace Exiv2 {
this copy and is responsible to delete it! this copy and is responsible to delete it!
*/ */
MakerNote* createSigmaMakerNote(bool alloc, MakerNote* createSigmaMakerNote(bool alloc,
const char* buf, const byte* buf,
long len, long len,
ByteOrder byteOrder, ByteOrder byteOrder,
long offset); long offset);
@ -96,7 +96,7 @@ namespace Exiv2 {
//! @name Manipulators //! @name Manipulators
//@{ //@{
int readHeader(const char* buf, int readHeader(const byte* buf,
long len, long len,
ByteOrder byteOrder); ByteOrder byteOrder);
//@} //@}

@ -20,13 +20,13 @@
*/ */
/* /*
File: tags.cpp File: tags.cpp
Version: $Name: $ $Revision: 1.28 $ Version: $Name: $ $Revision: 1.29 $
Author(s): Andreas Huggel (ahu) <ahuggel@gmx.net> Author(s): Andreas Huggel (ahu) <ahuggel@gmx.net>
History: 15-Jan-04, ahu: created History: 15-Jan-04, ahu: created
*/ */
// ***************************************************************************** // *****************************************************************************
#include "rcsid.hpp" #include "rcsid.hpp"
EXIV2_RCSID("@(#) $Name: $ $Revision: 1.28 $ $RCSfile: tags.cpp,v $") EXIV2_RCSID("@(#) $Name: $ $Revision: 1.29 $ $RCSfile: tags.cpp,v $")
// ***************************************************************************** // *****************************************************************************
// included header files // included header files
@ -779,7 +779,7 @@ namespace Exiv2 {
value.copy(buf.pData_, bigEndian); value.copy(buf.pData_, bigEndian);
// Hack: Skip the leading 8-Byte character code, truncate // Hack: Skip the leading 8-Byte character code, truncate
// trailing '\0's and let the stream take care of the remainder // trailing '\0's and let the stream take care of the remainder
std::string userComment(buf.pData_ + 8, buf.size_ - 8); std::string userComment(reinterpret_cast<char*>(buf.pData_) + 8, buf.size_ - 8);
std::string::size_type pos = userComment.find_last_not_of('\0'); std::string::size_type pos = userComment.find_last_not_of('\0');
os << userComment.substr(0, pos + 1); os << userComment.substr(0, pos + 1);
} }

@ -21,10 +21,10 @@
/*! /*!
@file tags.hpp @file tags.hpp
@brief Exif tag and type information @brief Exif tag and type information
@version $Name: $ $Revision: 1.22 $ @version $Name: $ $Revision: 1.23 $
@author Andreas Huggel (ahu) @author Andreas Huggel (ahu)
<a href="mailto:ahuggel@gmx.net">ahuggel@gmx.net</a> <a href="mailto:ahuggel@gmx.net">ahuggel@gmx.net</a>
@date 15-Jan-04, ahu: created @date 15-Jan-04, ahu: created<BR>
11-Feb-04, ahu: isolated as a component 11-Feb-04, ahu: isolated as a component
*/ */
#ifndef TAGS_HPP_ #ifndef TAGS_HPP_

@ -20,14 +20,14 @@
*/ */
/* /*
File: types.cpp File: types.cpp
Version: $Name: $ $Revision: 1.9 $ Version: $Name: $ $Revision: 1.10 $
Author(s): Andreas Huggel (ahu) <ahuggel@gmx.net> Author(s): Andreas Huggel (ahu) <ahuggel@gmx.net>
History: 26-Jan-04, ahu: created History: 26-Jan-04, ahu: created
11-Feb-04, ahu: isolated as a component 11-Feb-04, ahu: isolated as a component
*/ */
// ***************************************************************************** // *****************************************************************************
#include "rcsid.hpp" #include "rcsid.hpp"
EXIV2_RCSID("@(#) $Name: $ $Revision: 1.9 $ $RCSfile: types.cpp,v $") EXIV2_RCSID("@(#) $Name: $ $Revision: 1.10 $ $RCSfile: types.cpp,v $")
// ***************************************************************************** // *****************************************************************************
// included header files // included header files
@ -77,139 +77,139 @@ namespace Exiv2 {
// ************************************************************************* // *************************************************************************
// free functions // free functions
uint16 getUShort(const char* buf, ByteOrder byteOrder) uint16 getUShort(const byte* buf, ByteOrder byteOrder)
{ {
if (byteOrder == littleEndian) { if (byteOrder == littleEndian) {
return (unsigned char)buf[1] << 8 | (unsigned char)buf[0]; return (byte)buf[1] << 8 | (byte)buf[0];
} }
else { else {
return (unsigned char)buf[0] << 8 | (unsigned char)buf[1]; return (byte)buf[0] << 8 | (byte)buf[1];
} }
} }
uint32 getULong(const char* buf, ByteOrder byteOrder) uint32 getULong(const byte* buf, ByteOrder byteOrder)
{ {
if (byteOrder == littleEndian) { if (byteOrder == littleEndian) {
return (unsigned char)buf[3] << 24 | (unsigned char)buf[2] << 16 return (byte)buf[3] << 24 | (byte)buf[2] << 16
| (unsigned char)buf[1] << 8 | (unsigned char)buf[0]; | (byte)buf[1] << 8 | (byte)buf[0];
} }
else { else {
return (unsigned char)buf[0] << 24 | (unsigned char)buf[1] << 16 return (byte)buf[0] << 24 | (byte)buf[1] << 16
| (unsigned char)buf[2] << 8 | (unsigned char)buf[3]; | (byte)buf[2] << 8 | (byte)buf[3];
} }
} }
URational getURational(const char* buf, ByteOrder byteOrder) URational getURational(const byte* buf, ByteOrder byteOrder)
{ {
uint32 nominator = getULong(buf, byteOrder); uint32 nominator = getULong(buf, byteOrder);
uint32 denominator = getULong(buf + 4, byteOrder); uint32 denominator = getULong(buf + 4, byteOrder);
return std::make_pair(nominator, denominator); return std::make_pair(nominator, denominator);
} }
int16 getShort(const char* buf, ByteOrder byteOrder) int16 getShort(const byte* buf, ByteOrder byteOrder)
{ {
if (byteOrder == littleEndian) { if (byteOrder == littleEndian) {
return (unsigned char)buf[1] << 8 | (unsigned char)buf[0]; return (byte)buf[1] << 8 | (byte)buf[0];
} }
else { else {
return (unsigned char)buf[0] << 8 | (unsigned char)buf[1]; return (byte)buf[0] << 8 | (byte)buf[1];
} }
} }
int32 getLong(const char* buf, ByteOrder byteOrder) int32 getLong(const byte* buf, ByteOrder byteOrder)
{ {
if (byteOrder == littleEndian) { if (byteOrder == littleEndian) {
return (unsigned char)buf[3] << 24 | (unsigned char)buf[2] << 16 return (byte)buf[3] << 24 | (byte)buf[2] << 16
| (unsigned char)buf[1] << 8 | (unsigned char)buf[0]; | (byte)buf[1] << 8 | (byte)buf[0];
} }
else { else {
return (unsigned char)buf[0] << 24 | (unsigned char)buf[1] << 16 return (byte)buf[0] << 24 | (byte)buf[1] << 16
| (unsigned char)buf[2] << 8 | (unsigned char)buf[3]; | (byte)buf[2] << 8 | (byte)buf[3];
} }
} }
Rational getRational(const char* buf, ByteOrder byteOrder) Rational getRational(const byte* buf, ByteOrder byteOrder)
{ {
int32 nominator = getLong(buf, byteOrder); int32 nominator = getLong(buf, byteOrder);
int32 denominator = getLong(buf + 4, byteOrder); int32 denominator = getLong(buf + 4, byteOrder);
return std::make_pair(nominator, denominator); return std::make_pair(nominator, denominator);
} }
long us2Data(char* buf, uint16 s, ByteOrder byteOrder) long us2Data(byte* buf, uint16 s, ByteOrder byteOrder)
{ {
if (byteOrder == littleEndian) { if (byteOrder == littleEndian) {
buf[0] = (char)(s & 0x00ff); buf[0] = (byte)(s & 0x00ff);
buf[1] = (char)((s & 0xff00) >> 8); buf[1] = (byte)((s & 0xff00) >> 8);
} }
else { else {
buf[0] = (char)((s & 0xff00) >> 8); buf[0] = (byte)((s & 0xff00) >> 8);
buf[1] = (char)(s & 0x00ff); buf[1] = (byte)(s & 0x00ff);
} }
return 2; return 2;
} }
long ul2Data(char* buf, uint32 l, ByteOrder byteOrder) long ul2Data(byte* buf, uint32 l, ByteOrder byteOrder)
{ {
if (byteOrder == littleEndian) { if (byteOrder == littleEndian) {
buf[0] = (char)(l & 0x000000ff); buf[0] = (byte)(l & 0x000000ff);
buf[1] = (char)((l & 0x0000ff00) >> 8); buf[1] = (byte)((l & 0x0000ff00) >> 8);
buf[2] = (char)((l & 0x00ff0000) >> 16); buf[2] = (byte)((l & 0x00ff0000) >> 16);
buf[3] = (char)((l & 0xff000000) >> 24); buf[3] = (byte)((l & 0xff000000) >> 24);
} }
else { else {
buf[0] = (char)((l & 0xff000000) >> 24); buf[0] = (byte)((l & 0xff000000) >> 24);
buf[1] = (char)((l & 0x00ff0000) >> 16); buf[1] = (byte)((l & 0x00ff0000) >> 16);
buf[2] = (char)((l & 0x0000ff00) >> 8); buf[2] = (byte)((l & 0x0000ff00) >> 8);
buf[3] = (char)(l & 0x000000ff); buf[3] = (byte)(l & 0x000000ff);
} }
return 4; return 4;
} }
long ur2Data(char* buf, URational l, ByteOrder byteOrder) long ur2Data(byte* buf, URational l, ByteOrder byteOrder)
{ {
long o = ul2Data(buf, l.first, byteOrder); long o = ul2Data(buf, l.first, byteOrder);
o += ul2Data(buf+o, l.second, byteOrder); o += ul2Data(buf+o, l.second, byteOrder);
return o; return o;
} }
long s2Data(char* buf, int16 s, ByteOrder byteOrder) long s2Data(byte* buf, int16 s, ByteOrder byteOrder)
{ {
if (byteOrder == littleEndian) { if (byteOrder == littleEndian) {
buf[0] = (char)(s & 0x00ff); buf[0] = (byte)(s & 0x00ff);
buf[1] = (char)((s & 0xff00) >> 8); buf[1] = (byte)((s & 0xff00) >> 8);
} }
else { else {
buf[0] = (char)((s & 0xff00) >> 8); buf[0] = (byte)((s & 0xff00) >> 8);
buf[1] = (char)(s & 0x00ff); buf[1] = (byte)(s & 0x00ff);
} }
return 2; return 2;
} }
long l2Data(char* buf, int32 l, ByteOrder byteOrder) long l2Data(byte* buf, int32 l, ByteOrder byteOrder)
{ {
if (byteOrder == littleEndian) { if (byteOrder == littleEndian) {
buf[0] = (char)(l & 0x000000ff); buf[0] = (byte)(l & 0x000000ff);
buf[1] = (char)((l & 0x0000ff00) >> 8); buf[1] = (byte)((l & 0x0000ff00) >> 8);
buf[2] = (char)((l & 0x00ff0000) >> 16); buf[2] = (byte)((l & 0x00ff0000) >> 16);
buf[3] = (char)((l & 0xff000000) >> 24); buf[3] = (byte)((l & 0xff000000) >> 24);
} }
else { else {
buf[0] = (char)((l & 0xff000000) >> 24); buf[0] = (byte)((l & 0xff000000) >> 24);
buf[1] = (char)((l & 0x00ff0000) >> 16); buf[1] = (byte)((l & 0x00ff0000) >> 16);
buf[2] = (char)((l & 0x0000ff00) >> 8); buf[2] = (byte)((l & 0x0000ff00) >> 8);
buf[3] = (char)(l & 0x000000ff); buf[3] = (byte)(l & 0x000000ff);
} }
return 4; return 4;
} }
long r2Data(char* buf, Rational l, ByteOrder byteOrder) long r2Data(byte* buf, Rational l, ByteOrder byteOrder)
{ {
long o = l2Data(buf, l.first, byteOrder); long o = l2Data(buf, l.first, byteOrder);
o += l2Data(buf+o, l.second, byteOrder); o += l2Data(buf+o, l.second, byteOrder);
return o; return o;
} }
void hexdump(std::ostream& os, const char* buf, long len, long offset) void hexdump(std::ostream& os, const byte* buf, long len, long offset)
{ {
const std::string::size_type pos = 8 + 16 * 3 + 2; const std::string::size_type pos = 8 + 16 * 3 + 2;
const std::string align(pos, ' '); const std::string align(pos, ' ');
@ -221,7 +221,7 @@ namespace Exiv2 {
<< i + offset << " "; << i + offset << " ";
std::ostringstream ss; std::ostringstream ss;
do { do {
unsigned char c = buf[i]; byte c = buf[i];
os << std::setw(2) << std::setfill('0') os << std::setw(2) << std::setfill('0')
<< std::hex << (int)c << " "; << std::hex << (int)c << " ";
ss << ((int)c >= 31 && (int)c < 127 ? buf[i] : '.'); ss << ((int)c >= 31 && (int)c < 127 ? buf[i] : '.');

@ -21,10 +21,10 @@
/*! /*!
@file types.hpp @file types.hpp
@brief Type definitions for %Exiv2 and related functionality @brief Type definitions for %Exiv2 and related functionality
@version $Name: $ $Revision: 1.15 $ @version $Name: $ $Revision: 1.16 $
@author Andreas Huggel (ahu) @author Andreas Huggel (ahu)
<a href="mailto:ahuggel@gmx.net">ahuggel@gmx.net</a> <a href="mailto:ahuggel@gmx.net">ahuggel@gmx.net</a>
@date 09-Jan-04, ahu: created @date 09-Jan-04, ahu: created<BR>
11-Feb-04, ahu: isolated as a component 11-Feb-04, ahu: isolated as a component
*/ */
#ifndef TYPES_HPP_ #ifndef TYPES_HPP_
@ -54,6 +54,8 @@ namespace Exiv2 {
// ***************************************************************************** // *****************************************************************************
// type definitions // type definitions
//! 1 byte unsigned integer type.
typedef unsigned char byte;
//! 2 byte unsigned integer type. //! 2 byte unsigned integer type.
typedef unsigned short uint16; typedef unsigned short uint16;
//! 4 byte unsigned integer type. //! 4 byte unsigned integer type.
@ -132,33 +134,33 @@ namespace Exiv2 {
//! Default constructor //! Default constructor
DataBuf() : size_(0), pData_(0) {} DataBuf() : size_(0), pData_(0) {}
//! Constructor with an initial buffer size //! Constructor with an initial buffer size
DataBuf(long size) : size_(size), pData_(new char[size]) {} DataBuf(long size) : size_(size), pData_(new byte[size]) {}
//! Destructor, deletes the allocated buffer //! Destructor, deletes the allocated buffer
~DataBuf() { delete[] pData_; } ~DataBuf() { delete[] pData_; }
//! Allocate a data buffer of the given size //! Allocate a data buffer of the given size
void alloc(long size) void alloc(long size)
{ delete[] pData_; size_ = size; pData_ = new char[size]; } { if( size > size_ ){delete[] pData_; size_ = size; pData_ = new byte[size];} }
//! The current size of the buffer //! The current size of the buffer
long size_; long size_;
//! Pointer to the buffer, 0 if none has been allocated //! Pointer to the buffer, 0 if none has been allocated
char* pData_; byte* pData_;
}; // class DataBuf }; // class DataBuf
// ***************************************************************************** // *****************************************************************************
// free functions // free functions
//! Read a 2 byte unsigned short value from the data buffer //! Read a 2 byte unsigned short value from the data buffer
uint16 getUShort(const char* buf, ByteOrder byteOrder); uint16 getUShort(const byte* buf, ByteOrder byteOrder);
//! Read a 4 byte unsigned long value from the data buffer //! Read a 4 byte unsigned long value from the data buffer
uint32 getULong(const char* buf, ByteOrder byteOrder); uint32 getULong(const byte* buf, ByteOrder byteOrder);
//! Read an 8 byte unsigned rational value from the data buffer //! Read an 8 byte unsigned rational value from the data buffer
URational getURational(const char* buf, ByteOrder byteOrder); URational getURational(const byte* buf, ByteOrder byteOrder);
//! Read a 2 byte signed short value from the data buffer //! Read a 2 byte signed short value from the data buffer
int16 getShort(const char* buf, ByteOrder byteOrder); int16 getShort(const byte* buf, ByteOrder byteOrder);
//! Read a 4 byte signed long value from the data buffer //! Read a 4 byte signed long value from the data buffer
int32 getLong(const char* buf, ByteOrder byteOrder); int32 getLong(const byte* buf, ByteOrder byteOrder);
//! Read an 8 byte signed rational value from the data buffer //! Read an 8 byte signed rational value from the data buffer
Rational getRational(const char* buf, ByteOrder byteOrder); Rational getRational(const byte* buf, ByteOrder byteOrder);
//! Output operator for our fake rational //! Output operator for our fake rational
std::ostream& operator<<(std::ostream& os, const Rational& r); std::ostream& operator<<(std::ostream& os, const Rational& r);
@ -173,39 +175,39 @@ namespace Exiv2 {
@brief Convert an unsigned short to data, write the data to the buffer, @brief Convert an unsigned short to data, write the data to the buffer,
return number of bytes written. return number of bytes written.
*/ */
long us2Data(char* buf, uint16 s, ByteOrder byteOrder); long us2Data(byte* buf, uint16 s, ByteOrder byteOrder);
/*! /*!
@brief Convert an unsigned long to data, write the data to the buffer, @brief Convert an unsigned long to data, write the data to the buffer,
return number of bytes written. return number of bytes written.
*/ */
long ul2Data(char* buf, uint32 l, ByteOrder byteOrder); long ul2Data(byte* buf, uint32 l, ByteOrder byteOrder);
/*! /*!
@brief Convert an unsigned rational to data, write the data to the buffer, @brief Convert an unsigned rational to data, write the data to the buffer,
return number of bytes written. return number of bytes written.
*/ */
long ur2Data(char* buf, URational l, ByteOrder byteOrder); long ur2Data(byte* buf, URational l, ByteOrder byteOrder);
/*! /*!
@brief Convert a signed short to data, write the data to the buffer, @brief Convert a signed short to data, write the data to the buffer,
return number of bytes written. return number of bytes written.
*/ */
long s2Data(char* buf, int16 s, ByteOrder byteOrder); long s2Data(byte* buf, int16 s, ByteOrder byteOrder);
/*! /*!
@brief Convert a signed long to data, write the data to the buffer, @brief Convert a signed long to data, write the data to the buffer,
return number of bytes written. return number of bytes written.
*/ */
long l2Data(char* buf, int32 l, ByteOrder byteOrder); long l2Data(byte* buf, int32 l, ByteOrder byteOrder);
/*! /*!
@brief Convert a signed rational to data, write the data to the buffer, @brief Convert a signed rational to data, write the data to the buffer,
return number of bytes written. return number of bytes written.
*/ */
long r2Data(char* buf, Rational l, ByteOrder byteOrder); long r2Data(byte* buf, Rational l, ByteOrder byteOrder);
/*! /*!
@brief Print len bytes from buf in hex and ASCII format to the given @brief Print len bytes from buf in hex and ASCII format to the given
stream, prefixed with the position in the buffer adjusted by stream, prefixed with the position in the buffer adjusted by
offset. offset.
*/ */
void hexdump(std::ostream& os, const char* buf, long len, long offset =0); void hexdump(std::ostream& os, const byte* buf, long len, long offset =0);
/*! /*!
@brief Return the greatest common denominator of integers a and b. @brief Return the greatest common denominator of integers a and b.

@ -20,13 +20,13 @@
*/ */
/* /*
File: utils.cpp File: utils.cpp
Version: $Name: $ $Revision: 1.8 $ Version: $Name: $ $Revision: 1.9 $
Author(s): Andreas Huggel (ahu) <ahuggel@gmx.net> Author(s): Andreas Huggel (ahu) <ahuggel@gmx.net>
History: 08-Dec-03, ahu: created History: 08-Dec-03, ahu: created
*/ */
// ***************************************************************************** // *****************************************************************************
#include "rcsid.hpp" #include "rcsid.hpp"
EXIV2_RCSID("@(#) $Name: $ $Revision: 1.8 $ $RCSfile: utils.cpp,v $") EXIV2_RCSID("@(#) $Name: $ $Revision: 1.9 $ $RCSfile: utils.cpp,v $")
// ***************************************************************************** // *****************************************************************************
// included header files // included header files
@ -96,15 +96,15 @@ int Getopt::getopt(int argc, char* const argv[], const std::string& optstring)
if (path == "") return "."; if (path == "") return ".";
// Strip trailing slashes // Strip trailing slashes
std::string p = path; std::string p = path;
while (p.length() > 1 && p[p.length()-1] == '/') { while (p.length() > 1 && p[p.length()-1] == SEPERATOR_CHR) {
p = p.substr(0, p.length()-1); p = p.substr(0, p.length()-1);
} }
if (p == "/") return "/"; if (p == SEPERATOR_STR) return SEPERATOR_STR;
std::string::size_type idx = p.rfind('/'); std::string::size_type idx = p.rfind(SEPERATOR_CHR);
if (idx == std::string::npos) return "."; if (idx == std::string::npos) return ".";
if (idx == 0) return "/"; if (idx == 0) return SEPERATOR_STR;
p = p.substr(0, idx); p = p.substr(0, idx);
while (p.length() > 1 && p[p.length()-1] == '/') { while (p.length() > 1 && p[p.length()-1] == SEPERATOR_CHR) {
p = p.substr(0, p.length()-1); p = p.substr(0, p.length()-1);
} }
return p; return p;
@ -115,11 +115,11 @@ int Getopt::getopt(int argc, char* const argv[], const std::string& optstring)
if (path == "") return "."; if (path == "") return ".";
// Strip trailing slashes // Strip trailing slashes
std::string p = path; std::string p = path;
while (p.length() > 1 && p[p.length()-1] == '/') { while (p.length() > 1 && p[p.length()-1] == SEPERATOR_CHR) {
p = p.substr(0, p.length()-1); p = p.substr(0, p.length()-1);
} }
if (p == "/") return p; if (p == SEPERATOR_STR) return p;
std::string::size_type idx = p.rfind('/'); std::string::size_type idx = p.rfind(SEPERATOR_CHR);
if (idx != std::string::npos) p = p.substr(idx+1); if (idx != std::string::npos) p = p.substr(idx+1);
if (delsuffix) p = p.substr(0, p.length() - suffix(p).length()); if (delsuffix) p = p.substr(0, p.length() - suffix(p).length());
return p; return p;

@ -20,14 +20,14 @@
*/ */
/* /*
File: value.cpp File: value.cpp
Version: $Name: $ $Revision: 1.7 $ Version: $Name: $ $Revision: 1.8 $
Author(s): Andreas Huggel (ahu) <ahuggel@gmx.net> Author(s): Andreas Huggel (ahu) <ahuggel@gmx.net>
History: 26-Jan-04, ahu: created History: 26-Jan-04, ahu: created
11-Feb-04, ahu: isolated as a component 11-Feb-04, ahu: isolated as a component
*/ */
// ***************************************************************************** // *****************************************************************************
#include "rcsid.hpp" #include "rcsid.hpp"
EXIV2_RCSID("@(#) $Name: $ $Revision: 1.7 $ $RCSfile: value.cpp,v $") EXIV2_RCSID("@(#) $Name: $ $Revision: 1.8 $ $RCSfile: value.cpp,v $")
// ***************************************************************************** // *****************************************************************************
// included header files // included header files
@ -108,10 +108,10 @@ namespace Exiv2 {
return *this; return *this;
} }
void DataValue::read(const char* buf, long len, ByteOrder byteOrder) void DataValue::read(const byte* buf, long len, ByteOrder byteOrder)
{ {
// byteOrder not needed // byteOrder not needed
value_ = std::string(buf, len); value_ = std::string(reinterpret_cast<const char*>(buf), len);
} }
void DataValue::read(const std::string& buf) void DataValue::read(const std::string& buf)
@ -124,10 +124,12 @@ namespace Exiv2 {
} }
} }
long DataValue::copy(char* buf, ByteOrder byteOrder) const long DataValue::copy(byte* buf, ByteOrder byteOrder) const
{ {
// byteOrder not needed // byteOrder not needed
return static_cast<long>(value_.copy(buf, value_.size())); return static_cast<long>(
value_.copy(reinterpret_cast<char*>(buf), value_.size())
);
} }
long DataValue::size() const long DataValue::size() const
@ -144,7 +146,7 @@ namespace Exiv2 {
{ {
std::string::size_type end = value_.size(); std::string::size_type end = value_.size();
for (std::string::size_type i = 0; i != end; ++i) { for (std::string::size_type i = 0; i != end; ++i) {
os << static_cast<int>(static_cast<unsigned char>(value_[i])) os << static_cast<int>(static_cast<byte>(value_[i]))
<< " "; << " ";
} }
return os; return os;
@ -158,10 +160,10 @@ namespace Exiv2 {
return *this; return *this;
} }
void AsciiValue::read(const char* buf, long len, ByteOrder byteOrder) void AsciiValue::read(const byte* buf, long len, ByteOrder byteOrder)
{ {
// byteOrder not needed // byteOrder not needed
value_ = std::string(buf, len); value_ = std::string(reinterpret_cast<const char*>(buf), len);
} }
void AsciiValue::read(const std::string& buf) void AsciiValue::read(const std::string& buf)
@ -170,10 +172,12 @@ namespace Exiv2 {
if (value_[value_.size()-1] != '\0') value_ += '\0'; if (value_[value_.size()-1] != '\0') value_ += '\0';
} }
long AsciiValue::copy(char* buf, ByteOrder byteOrder) const long AsciiValue::copy(byte* buf, ByteOrder byteOrder) const
{ {
// byteOrder not needed // byteOrder not needed
return static_cast<long>(value_.copy(buf, value_.size())); return static_cast<long>(
value_.copy(reinterpret_cast<char*>(buf), value_.size())
);
} }
long AsciiValue::size() const long AsciiValue::size() const

@ -21,7 +21,7 @@
/*! /*!
@file value.hpp @file value.hpp
@brief Value interface and concrete subclasses @brief Value interface and concrete subclasses
@version $Name: $ $Revision: 1.11 $ @version $Name: $ $Revision: 1.12 $
@author Andreas Huggel (ahu) @author Andreas Huggel (ahu)
<a href="mailto:ahuggel@gmx.net">ahuggel@gmx.net</a> <a href="mailto:ahuggel@gmx.net">ahuggel@gmx.net</a>
@date 09-Jan-04, ahu: created @date 09-Jan-04, ahu: created
@ -75,7 +75,7 @@ namespace Exiv2 {
@param len Number of bytes in the data buffer @param len Number of bytes in the data buffer
@param byteOrder Applicable byte order (little or big endian). @param byteOrder Applicable byte order (little or big endian).
*/ */
virtual void read(const char* buf, long len, ByteOrder byteOrder) =0; virtual void read(const byte* buf, long len, ByteOrder byteOrder) =0;
/*! /*!
@brief Set the value from a string buffer. The format of the string @brief Set the value from a string buffer. The format of the string
corresponds to that of the write() method, i.e., a string corresponds to that of the write() method, i.e., a string
@ -106,7 +106,7 @@ namespace Exiv2 {
@param byteOrder Applicable byte order (little or big endian). @param byteOrder Applicable byte order (little or big endian).
@return Number of characters written. @return Number of characters written.
*/ */
virtual long copy(char* buf, ByteOrder byteOrder) const =0; virtual long copy(byte* buf, ByteOrder byteOrder) const =0;
//! Return the number of components of the value //! Return the number of components of the value
virtual long count() const =0; virtual long count() const =0;
//! Return the size of the value in bytes //! Return the size of the value in bytes
@ -218,7 +218,7 @@ namespace Exiv2 {
@param len Number of bytes in the data buffer @param len Number of bytes in the data buffer
@param byteOrder Byte order. Not needed. @param byteOrder Byte order. Not needed.
*/ */
virtual void read(const char* buf, virtual void read(const byte* buf,
long len, long len,
ByteOrder byteOrder =invalidByteOrder); ByteOrder byteOrder =invalidByteOrder);
//! Set the data from a string of integer values (e.g., "0 1 2 3") //! Set the data from a string of integer values (e.g., "0 1 2 3")
@ -240,7 +240,7 @@ namespace Exiv2 {
@param byteOrder Byte order. Not needed. @param byteOrder Byte order. Not needed.
@return Number of characters written. @return Number of characters written.
*/ */
virtual long copy(char* buf, ByteOrder byteOrder =invalidByteOrder) const; virtual long copy(byte* buf, ByteOrder byteOrder =invalidByteOrder) const;
virtual long count() const { return size(); } virtual long count() const { return size(); }
virtual long size() const; virtual long size() const;
virtual DataValue* clone() const; virtual DataValue* clone() const;
@ -281,7 +281,7 @@ namespace Exiv2 {
@param len Number of bytes in the data buffer @param len Number of bytes in the data buffer
@param byteOrder Byte order. Not needed. @param byteOrder Byte order. Not needed.
*/ */
virtual void read(const char* buf, virtual void read(const byte* buf,
long len, long len,
ByteOrder byteOrder =invalidByteOrder); ByteOrder byteOrder =invalidByteOrder);
/*! /*!
@ -307,7 +307,7 @@ namespace Exiv2 {
@param byteOrder Byte order. Not used. @param byteOrder Byte order. Not used.
@return Number of characters written. @return Number of characters written.
*/ */
virtual long copy(char* buf, ByteOrder byteOrder =invalidByteOrder) const; virtual long copy(byte* buf, ByteOrder byteOrder =invalidByteOrder) const;
virtual long count() const { return size(); } virtual long count() const { return size(); }
virtual long size() const; virtual long size() const;
virtual AsciiValue* clone() const; virtual AsciiValue* clone() const;
@ -366,7 +366,7 @@ namespace Exiv2 {
//@{ //@{
//! Assignment operator. //! Assignment operator.
ValueType<T>& operator=(const ValueType<T>& rhs); ValueType<T>& operator=(const ValueType<T>& rhs);
virtual void read(const char* buf, long len, ByteOrder byteOrder); virtual void read(const byte* buf, long len, ByteOrder byteOrder);
/*! /*!
@brief Set the data from a string of values of type T (e.g., @brief Set the data from a string of values of type T (e.g.,
"0 1 2 3" or "1/2 1/3 1/4" depending on what T is). "0 1 2 3" or "1/2 1/3 1/4" depending on what T is).
@ -378,7 +378,7 @@ namespace Exiv2 {
//! @name Accessors //! @name Accessors
//@{ //@{
virtual long copy(char* buf, ByteOrder byteOrder) const; virtual long copy(byte* buf, ByteOrder byteOrder) const;
virtual long count() const { return static_cast<long>(value_.size()); } virtual long count() const { return static_cast<long>(value_.size()); }
virtual long size() const; virtual long size() const;
virtual ValueType<T>* clone() const; virtual ValueType<T>* clone() const;
@ -432,40 +432,40 @@ namespace Exiv2 {
@param byteOrder Applicable byte order (little or big endian). @param byteOrder Applicable byte order (little or big endian).
@return A value of type T. @return A value of type T.
*/ */
template<typename T> T getValue(const char* buf, ByteOrder byteOrder); template<typename T> T getValue(const byte* buf, ByteOrder byteOrder);
// Specialization for a 2 byte unsigned short value. // Specialization for a 2 byte unsigned short value.
template<> template<>
inline uint16 getValue(const char* buf, ByteOrder byteOrder) inline uint16 getValue(const byte* buf, ByteOrder byteOrder)
{ {
return getUShort(buf, byteOrder); return getUShort(buf, byteOrder);
} }
// Specialization for a 4 byte unsigned long value. // Specialization for a 4 byte unsigned long value.
template<> template<>
inline uint32 getValue(const char* buf, ByteOrder byteOrder) inline uint32 getValue(const byte* buf, ByteOrder byteOrder)
{ {
return getULong(buf, byteOrder); return getULong(buf, byteOrder);
} }
// Specialization for an 8 byte unsigned rational value. // Specialization for an 8 byte unsigned rational value.
template<> template<>
inline URational getValue(const char* buf, ByteOrder byteOrder) inline URational getValue(const byte* buf, ByteOrder byteOrder)
{ {
return getURational(buf, byteOrder); return getURational(buf, byteOrder);
} }
// Specialization for a 2 byte signed short value. // Specialization for a 2 byte signed short value.
template<> template<>
inline int16 getValue(const char* buf, ByteOrder byteOrder) inline int16 getValue(const byte* buf, ByteOrder byteOrder)
{ {
return getShort(buf, byteOrder); return getShort(buf, byteOrder);
} }
// Specialization for a 4 byte signed long value. // Specialization for a 4 byte signed long value.
template<> template<>
inline int32 getValue(const char* buf, ByteOrder byteOrder) inline int32 getValue(const byte* buf, ByteOrder byteOrder)
{ {
return getLong(buf, byteOrder); return getLong(buf, byteOrder);
} }
// Specialization for an 8 byte signed rational value. // Specialization for an 8 byte signed rational value.
template<> template<>
inline Rational getValue(const char* buf, ByteOrder byteOrder) inline Rational getValue(const byte* buf, ByteOrder byteOrder)
{ {
return getRational(buf, byteOrder); return getRational(buf, byteOrder);
} }
@ -482,13 +482,13 @@ namespace Exiv2 {
@param byteOrder Applicable byte order (little or big endian). @param byteOrder Applicable byte order (little or big endian).
@return The number of bytes written to the buffer. @return The number of bytes written to the buffer.
*/ */
template<typename T> long toData(char* buf, T t, ByteOrder byteOrder); template<typename T> long toData(byte* buf, T t, ByteOrder byteOrder);
/*! /*!
@brief Specialization to write an unsigned short to the data buffer. @brief Specialization to write an unsigned short to the data buffer.
Return the number of bytes written. Return the number of bytes written.
*/ */
template<> template<>
inline long toData(char* buf, uint16 t, ByteOrder byteOrder) inline long toData(byte* buf, uint16 t, ByteOrder byteOrder)
{ {
return us2Data(buf, t, byteOrder); return us2Data(buf, t, byteOrder);
} }
@ -497,7 +497,7 @@ namespace Exiv2 {
Return the number of bytes written. Return the number of bytes written.
*/ */
template<> template<>
inline long toData(char* buf, uint32 t, ByteOrder byteOrder) inline long toData(byte* buf, uint32 t, ByteOrder byteOrder)
{ {
return ul2Data(buf, t, byteOrder); return ul2Data(buf, t, byteOrder);
} }
@ -506,7 +506,7 @@ namespace Exiv2 {
Return the number of bytes written. Return the number of bytes written.
*/ */
template<> template<>
inline long toData(char* buf, URational t, ByteOrder byteOrder) inline long toData(byte* buf, URational t, ByteOrder byteOrder)
{ {
return ur2Data(buf, t, byteOrder); return ur2Data(buf, t, byteOrder);
} }
@ -515,7 +515,7 @@ namespace Exiv2 {
Return the number of bytes written. Return the number of bytes written.
*/ */
template<> template<>
inline long toData(char* buf, int16 t, ByteOrder byteOrder) inline long toData(byte* buf, int16 t, ByteOrder byteOrder)
{ {
return s2Data(buf, t, byteOrder); return s2Data(buf, t, byteOrder);
} }
@ -524,7 +524,7 @@ namespace Exiv2 {
Return the number of bytes written. Return the number of bytes written.
*/ */
template<> template<>
inline long toData(char* buf, int32 t, ByteOrder byteOrder) inline long toData(byte* buf, int32 t, ByteOrder byteOrder)
{ {
return l2Data(buf, t, byteOrder); return l2Data(buf, t, byteOrder);
} }
@ -533,7 +533,7 @@ namespace Exiv2 {
Return the number of bytes written. Return the number of bytes written.
*/ */
template<> template<>
inline long toData(char* buf, Rational t, ByteOrder byteOrder) inline long toData(byte* buf, Rational t, ByteOrder byteOrder)
{ {
return r2Data(buf, t, byteOrder); return r2Data(buf, t, byteOrder);
} }
@ -548,7 +548,7 @@ namespace Exiv2 {
} }
template<typename T> template<typename T>
void ValueType<T>::read(const char* buf, long len, ByteOrder byteOrder) void ValueType<T>::read(const byte* buf, long len, ByteOrder byteOrder)
{ {
value_.clear(); value_.clear();
for (long i = 0; i < len; i += TypeInfo::typeSize(typeId())) { for (long i = 0; i < len; i += TypeInfo::typeSize(typeId())) {
@ -568,7 +568,7 @@ namespace Exiv2 {
} }
template<typename T> template<typename T>
long ValueType<T>::copy(char* buf, ByteOrder byteOrder) const long ValueType<T>::copy(byte* buf, ByteOrder byteOrder) const
{ {
long offset = 0; long offset = 0;
typename ValueList::const_iterator end = value_.end(); typename ValueList::const_iterator end = value_.end();

Loading…
Cancel
Save