libopenraw
|
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