// ***************************************************************************** /* * Copyright (C) 2006 Olivier Tilloy * * This program is part of the pyexiv2 distribution. * * pyexiv2 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. * * pyexiv2 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 pyexiv2; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA. */ /* File: libpyexiv2.cpp Author(s): Olivier Tilloy History: 28-Dec-06, Olivier Tilloy: created 30-Dec-06, Olivier Tilloy: implemented IPTC-related methods 03-Jan-07, Olivier Tilloy: implemented getThumbnailData() */ // ***************************************************************************** #include "libpyexiv2.hpp" namespace LibPyExiv2 { // Base constructor Image::Image(std::string filename) { _filename = filename; try { _image = Exiv2::ImageFactory::open(filename); assert(_image.get() != 0); } catch(Exiv2::AnyError & e) { std::cerr << ">>> Image::Image(): caught Exiv2 exception '" << e << "'!"; } _dataRead = false; } // Copy constructor Image::Image(const Image & image) { _filename = image._filename; try { _image = Exiv2::ImageFactory::open(_filename); assert(_image.get() != 0); } catch(Exiv2::AnyError & e) { std::cerr << ">>> Image::Image(): caught Exiv2 exception '" << e << "'!"; } _dataRead = false; } void Image::readMetadata() { try { _image->readMetadata(); _exifData = _image->exifData(); _iptcData = _image->iptcData(); _dataRead = true; } catch(Exiv2::Error & e) { // An error occured while reading the metadata _dataRead = false; std::cerr << ">>> Image::readMetadata(): caught Exiv2 exception '" << e << "'!"; } } void Image::writeMetadata() { if(_dataRead) { try { _image->setExifData(_exifData); _image->setIptcData(_iptcData); _image->writeMetadata(); } catch(Exiv2::Error & e) { // An error occured while writing the metadata std::cerr << ">>> Image::writeMetadata(): caught Exiv2 exception '" << e << "'!"; } } } boost::python::list Image::getAvailableExifTags() { boost::python::list list; if(_dataRead) { for(Exiv2::ExifMetadata::iterator i = _exifData.begin() ; i != _exifData.end() ; ++i) { list.append(i->key()); } return list; } else { std::cerr << ">>> Image::getAvailableExifTags(): metadata not read yet, call Image::readMetadata() first" << std::endl; // The returned list is empty return list; } } boost::python::tuple Image::getExifTag(std::string key) { if(_dataRead) { try { Exiv2::ExifKey exifKey = Exiv2::ExifKey(key); Exiv2::ExifMetadata::iterator i = _exifData.findKey(exifKey); if(i != _exifData.end()) { Exiv2::Exifdatum exifDatum = _exifData[key]; return boost::python::make_tuple(exifDatum.typeName(), exifDatum.toString()); } else { // The key was not found std::cerr << ">>> Image::getExifTag(): tag '" << key << "' not found" << std::endl; return boost::python::make_tuple(std::string(""), std::string("")); } } catch(Exiv2::Error & e) { // The key is not a valid Exif tag key std::cerr << ">>> Image::getExifTag(): unknown key '" << key << "'" << std::endl; return boost::python::make_tuple(std::string(""), std::string("")); } } else { std::cerr << ">>> Image::getExifTag(): metadata not read yet, call Image::readMetadata() first" << std::endl; return boost::python::make_tuple(std::string(""), std::string("")); } } std::string Image::getExifTagToString(std::string key) { if(_dataRead) { try { Exiv2::ExifKey exifKey = Exiv2::ExifKey(key); Exiv2::ExifMetadata::iterator i = _exifData.findKey(exifKey); if(i != _exifData.end()) { Exiv2::Exifdatum exifDatum = _exifData[key]; std::ostringstream buffer; buffer << exifDatum; return buffer.str(); } else { // The key was not found std::cerr << ">>> Image::getExifTagToString(): tag '" << key << "' not found" << std::endl; return std::string(""); } } catch(Exiv2::Error & e) { // The key is not a valid Exif tag key std::cerr << ">>> Image::getExifTagToString(): unknown key '" << key << "'" << std::endl; return std::string(""); } } else { std::cerr << ">>> Image::getExifTagToString(): metadata not read yet, call Image::readMetadata() first" << std::endl; return std::string(""); } } boost::python::tuple Image::setExifTag(std::string key, std::string value) { boost::python::tuple returnValue; if(_dataRead) { try { Exiv2::ExifKey exifKey = Exiv2::ExifKey(key); Exiv2::ExifMetadata::iterator i = _exifData.findKey(exifKey); if(i != _exifData.end()) { Exiv2::Exifdatum exifDatum = _exifData[key]; returnValue = boost::python::make_tuple(exifDatum.typeName(), exifDatum.toString()); // First erase the existing tag: in some case (and // I don't know why), the new value won't replace // the old one if not previously erased... _exifData.erase(i); } else { // The key was not found std::cerr << ">>> Image::setExifTag(): tag '" << key << "' not found" << std::endl; returnValue = boost::python::make_tuple(std::string(""), std::string("")); } _exifData[key] = value; return returnValue; } catch(Exiv2::Error & e) { // The key is not a valid Exif tag key std::cerr << ">>> Image::setExifTag(): unknown key '" << key << "'" << std::endl; return boost::python::make_tuple(std::string(""), std::string("")); } } else { std::cerr << ">>> Image::setExifTag(): metadata not read yet, call Image::readMetadata() first" << std::endl; return boost::python::make_tuple(std::string(""), std::string("")); } } boost::python::tuple Image::deleteExifTag(std::string key) { boost::python::tuple returnValue; if(_dataRead) { try { Exiv2::ExifKey exifKey = Exiv2::ExifKey(key); Exiv2::ExifMetadata::iterator i = _exifData.findKey(exifKey); if(i != _exifData.end()) { Exiv2::Exifdatum exifDatum = _exifData[key]; returnValue = boost::python::make_tuple(exifDatum.typeName(), exifDatum.toString()); _exifData.erase(i); } else { // The key was not found std::cerr << ">>> Image::deleteExifTag(): tag '" << key << "' not found" << std::endl; returnValue = boost::python::make_tuple(std::string(""), std::string("")); } return returnValue; } catch(Exiv2::Error & e) { // The key is not a valid Exif tag key std::cerr << ">>> Image::deleteExifTag(): unknown key '" << key << "'" << std::endl; return boost::python::make_tuple(std::string(""), std::string("")); } } else { std::cerr << ">>> Image::deleteExifTag(): metadata not read yet, call Image::readMetadata() first" << std::endl; return boost::python::make_tuple(std::string(""), std::string("")); } } // returns a list containing the keys of all the IPTC tags available in // the image boost::python::list Image::getAvailableIptcTags() { boost::python::list list; if(_dataRead) { for(Exiv2::IptcMetadata::iterator i = _iptcData.begin() ; i != _iptcData.end() ; i++) { list.append(i->key()); } return list; } else { std::cerr << ">>> Image::getAvailableIptcTags(): metadata not read yet, call Image::readMetadata() first" << std::endl; // The returned list is empty return list; } } boost::python::tuple Image::getIptcTag(std::string key) { if(_dataRead) { try { Exiv2::IptcKey iptcKey = Exiv2::IptcKey(key); Exiv2::IptcMetadata::iterator i = _iptcData.findKey(iptcKey); if(i != _iptcData.end()) { Exiv2::Iptcdatum iptcDatum = _iptcData[key]; return boost::python::make_tuple(iptcDatum.typeName(), iptcDatum.toString()); } else { // The key was not found std::cerr << ">>> Image::getIptcTag(): tag '" << key << "' not found" << std::endl; return boost::python::make_tuple(std::string(""), std::string("")); } } catch(Exiv2::Error & e) { // The key is not a valid Iptc tag key std::cerr << ">>> Image::getIptcTag(): unknown key '" << key << "'" << std::endl; return boost::python::make_tuple(std::string(""), std::string("")); } } else { std::cerr << ">>> Image::getIptcTag(): metadata not read yet, call Image::readMetadata() first" << std::endl; return boost::python::make_tuple(std::string(""), std::string("")); } } boost::python::tuple Image::setIptcTag(std::string key, std::string value) { boost::python::tuple returnValue; if(_dataRead) { try { Exiv2::IptcKey iptcKey = Exiv2::IptcKey(key); Exiv2::IptcMetadata::iterator i = _iptcData.findKey(iptcKey); if(i != _iptcData.end()) { Exiv2::Iptcdatum iptcDatum = _iptcData[key]; returnValue = boost::python::make_tuple(iptcDatum.typeName(), iptcDatum.toString()); // First erase the existing tag _iptcData.erase(i); } else { // The key was not found std::cerr << ">>> Image::setIptcTag(): tag '" << key << "' not found" << std::endl; returnValue = boost::python::make_tuple(std::string(""), std::string("")); } _iptcData[key] = value; return returnValue; } catch(Exiv2::Error & e) { // The key is not a valid Iptc tag key std::cerr << ">>> Image::setIptcTag(): unknown key '" << key << "'" << std::endl; return boost::python::make_tuple(std::string(""), std::string("")); } } else { std::cerr << ">>> Image::setIptcTag(): metadata not read yet, call Image::readMetadata() first" << std::endl; return boost::python::make_tuple(std::string(""), std::string("")); } } boost::python::tuple Image::deleteIptcTag(std::string key) { boost::python::tuple returnValue; if(_dataRead) { try { Exiv2::IptcKey iptcKey = Exiv2::IptcKey(key); Exiv2::IptcMetadata::iterator i = _iptcData.findKey(iptcKey); if(i != _iptcData.end()) { Exiv2::Iptcdatum iptcDatum = _iptcData[key]; returnValue = boost::python::make_tuple(iptcDatum.typeName(), iptcDatum.toString()); _iptcData.erase(i); } else { // The key was not found std::cerr << ">>> Image::deleteIptcTag(): tag '" << key << "' not found" << std::endl; returnValue = boost::python::make_tuple(std::string(""), std::string("")); } return returnValue; } catch(Exiv2::Error & e) { // The key is not a valid Iptc tag key std::cerr << ">>> Image::deleteIptcTag(): unknown key '" << key << "'" << std::endl; return boost::python::make_tuple(std::string(""), std::string("")); } } else { std::cerr << ">>> Image::deleteIptcTag(): metadata not read yet, call Image::readMetadata() first" << std::endl; return boost::python::make_tuple(std::string(""), std::string("")); } } boost::python::tuple Image::getThumbnailData() { if(_dataRead) { Exiv2::Thumbnail::AutoPtr thumbnail = _exifData.getThumbnail(); if (thumbnail.get() != 0) { std::string format(_exifData.thumbnailFormat()); // Copy the data buffer in a string. Since the data buffer can // contain null char ('\x00'), the string cannot be simply // constructed like that: // std::string data((char*) dataBuffer.pData_); // because it would be truncated after the first occurence of a // null char. Therefore, it has to be copied char by char. Exiv2::DataBuf dataBuffer = _exifData.copyThumbnail(); char* charData = (char*) dataBuffer.pData_; long dataLen = dataBuffer.size_; std::string data; for(long i = 0; i < dataLen; ++i) { data.append(1, charData[i]); } return boost::python::make_tuple(format, data); } else { std::cerr << ">>> Image::getThumbnailData(): cannot access thumbnail" << std::endl; return boost::python::make_tuple(std::string(""), std::string("")); } } else { std::cerr << ">>> Image::getThumbnailData(): metadata not read yet, call Image::readMetadata() first" << std::endl; return boost::python::make_tuple(std::string(""), std::string("")); } } bool Image::setThumbnailData(boost::python::tuple data) { //TODO return true; } } // End of namespace LibPyExiv2