ifddir.cpp
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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