ifddir.cpp

00001 /*
00002  * libopenraw - ifddir.cpp
00003  *
00004  * Copyright (C) 2006-2007 Hubert Figuiere
00005  *
00006  * This library is free software: you can redistribute it and/or
00007  * modify it under the terms of the GNU Lesser General Public License
00008  * as published by the Free Software Foundation, either version 3 of
00009  * the License, or (at your option) any later version.
00010  *
00011  * This library is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  * Lesser General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU Lesser General Public
00017  * License along with this library.  If not, see
00018  * <http://www.gnu.org/licenses/>.
00019  */
00020 
00021 
00022 #include <libopenraw/types.h>
00023 
00024 #include "debug.h"
00025 #include "exception.h"
00026 #include "ifd.h"
00027 #include "io/stream.h"
00028 #include "ifdfilecontainer.h"
00029 #include "ifddir.h"
00030 
00031 using namespace Debug;
00032 
00033 namespace OpenRaw {
00034 
00035     namespace Internals {
00036 
00037         bool IFDDir::isPrimary::operator()(const Ref &dir)
00038         {
00039             uint32_t subtype = 1; 
00040             return dir->getValue(IFD::EXIF_TAG_NEW_SUBFILE_TYPE, subtype)
00041                 && (subtype == 0);
00042         }
00043 
00044         bool IFDDir::isThumbnail::operator()(const Ref &dir)
00045         {
00046             uint32_t subtype = 0; 
00047             return dir->getValue(IFD::EXIF_TAG_NEW_SUBFILE_TYPE, subtype)
00048                 && (subtype == 1);
00049         }
00050 
00051         IFDDir::IFDDir(off_t _offset, IFDFileContainer & _container)
00052             : m_offset(_offset), m_container(_container), 
00053                 m_entries()
00054         {
00055             
00056         }
00057 
00058         IFDDir::~IFDDir()
00059         {
00060 
00061         }
00062 
00063         bool IFDDir::load()
00064         {
00065             Trace(DEBUG1) << "IFDDir::load() m_offset =" << m_offset << "\n";
00066             int16_t numEntries = 0;
00067             IO::Stream *file = m_container.file();
00068             m_entries.clear();
00069             file->seek(m_offset, SEEK_SET);
00070             m_container.readInt16(file, numEntries);
00071 
00072             for(int16_t i = 0; i < numEntries; i++) {
00073                 uint16_t id;
00074                 int16_t type;
00075                 int32_t count;
00076                 uint32_t data;
00077                 m_container.readUInt16(file, id);
00078                 m_container.readInt16(file, type);
00079                 m_container.readInt32(file, count);
00080                 file->read(&data, 4);
00081                 IFDEntry::Ref entry(new IFDEntry(id, type, 
00082                                                  count, data, m_container));
00083                 m_entries[id] = entry;
00084             }
00085 
00086             return true;
00087         }
00088 
00089         IFDEntry::Ref IFDDir::getEntry(uint16_t id) const
00090         {
00091             std::map<uint16_t, IFDEntry::Ref>::const_iterator iter;
00092             iter = m_entries.find(id);
00093             if (iter != m_entries.end()) {
00094                 return iter->second;
00095             }
00096             return IFDEntry::Ref((IFDEntry*)NULL);
00097         }
00098 
00099 
00100         bool IFDDir::getIntegerValue(uint16_t id, uint32_t &v)
00101         {
00102             bool success = false;
00103             IFDEntry::Ref e = getEntry(id);
00104             if (e != NULL) {
00105                 try {
00106                     switch(e->type())
00107                     {
00108                     case IFD::EXIF_FORMAT_LONG:
00109                         v = IFDTypeTrait<uint32_t>::get(*e);
00110                         success = true;
00111                         break;
00112                     case IFD::EXIF_FORMAT_SHORT:
00113                         v = IFDTypeTrait<uint16_t>::get(*e);
00114                         success = true;
00115                         break;
00116                     default:
00117                         break;
00118                     }
00119                 }
00120                 catch(const std::exception & ex) {
00121                     Trace(ERROR) << "Exception raised " << ex.what() 
00122                                              << " fetch integer value for " << id << "\n";
00123                 }
00124             }
00125             return success;
00126         }
00127 
00128 
00129         off_t IFDDir::nextIFD()
00130         {
00131             int16_t numEntries;
00132             IO::Stream *file = m_container.file();
00133 
00134             if(m_entries.size() == 0) {
00135                 file->seek(m_offset, SEEK_SET);
00136                 m_container.readInt16(file, numEntries);
00137                 Trace(DEBUG1) << "numEntries =" << numEntries 
00138                                     << " shifting " << (numEntries * 12) + 2
00139                                     << "bytes\n";
00140             }
00141             else {
00142                 numEntries = m_entries.size();
00143             }
00144 
00145             file->seek(m_offset + (numEntries * 12) + 2, SEEK_SET);
00146             int32_t next;
00147             m_container.readInt32(file, next);
00148             return next;
00149         }
00150         
00154         IFDDir::Ref IFDDir::getSubIFD(uint32_t idx) const
00155         {
00156             std::vector<uint32_t> offsets;
00157             IFDEntry::Ref e = getEntry(IFD::EXIF_TAG_SUB_IFDS);
00158             if (e != NULL) {
00159                 try {
00160                     e->getArray(offsets);
00161                     if (idx >= offsets.size()) {
00162                         Ref ref(new IFDDir(offsets[idx], m_container));
00163                         ref->load();
00164                         return ref;
00165                     }
00166                 }
00167                 catch(const std::exception &ex) {
00168                     Trace(ERROR) << "Exception " << ex.what() << "\n";
00169                 }
00170             }
00171             return Ref(static_cast<IFDDir*>(NULL));
00172         }
00173 
00174 
00175         bool IFDDir::getSubIFDs(std::vector<IFDDir::Ref> & ifds) 
00176         {
00177             bool success = false;
00178             std::vector<uint32_t> offsets;
00179             IFDEntry::Ref e = getEntry(IFD::EXIF_TAG_SUB_IFDS);
00180             if (e != NULL) {
00181                 try {
00182                     e->getArray(offsets);
00183                     for (std::vector<uint32_t>::const_iterator iter = offsets.begin();
00184                              iter != offsets.end(); iter++) {
00185                         Ref ifd(new IFDDir(*iter, m_container));
00186                         ifd->load();
00187                         ifds.push_back(ifd);
00188                     }
00189                     success = true;
00190                 }
00191                 catch(const std::exception &ex) {
00192                     Trace(ERROR) << "Exception " << ex.what() << "\n";                  
00193                 }
00194             }
00195             return success;
00196         }
00197 
00201         IFDDir::Ref IFDDir::getExifIFD()
00202         {
00203             bool success = false;
00204             uint32_t val_offset = 0;
00205             success = getValue(IFD::EXIF_TAG_EXIF_IFD_POINTER, val_offset);
00206             if (success) {
00207                 Trace(DEBUG1) << "Exif IFD offset (uncorrected) = " << val_offset 
00208                              << "\n";
00209                 val_offset += m_container.exifOffsetCorrection();
00210                 Trace(DEBUG1) << "Exif IFD offset = " << val_offset << "\n";
00211                 Ref ref(new IFDDir(val_offset, m_container));
00212                 ref->load();
00213                 return ref;
00214             }
00215             else {
00216                 Trace(DEBUG1) << "Exif IFD offset not found.\n";                
00217             }
00218             return Ref(static_cast<IFDDir*>(NULL));
00219         }
00220 
00221     }
00222 }
00223 
Generated on Thu Jul 29 20:40:27 2010 for libopenraw by  doxygen 1.6.3