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 IFDDir::IFDDir(off_t _offset, IFDFileContainer & _container)
00038 : m_offset(_offset), m_container(_container),
00039 m_entries()
00040 {
00041
00042 }
00043
00044 IFDDir::~IFDDir()
00045 {
00046
00047 }
00048
00049 bool IFDDir::load()
00050 {
00051 Trace(DEBUG1) << "IFDDir::load() m_offset =" << m_offset << "\n";
00052 int16_t numEntries = 0;
00053 IO::Stream *file = m_container.file();
00054 m_entries.clear();
00055 file->seek(m_offset, SEEK_SET);
00056 m_container.readInt16(file, numEntries);
00057
00058 Trace(DEBUG1) << "num =" << numEntries << "\n";
00059
00060 for(int16_t i = 0; i < numEntries; i++) {
00061 int16_t id;
00062 int16_t type;
00063 int32_t count;
00064 uint32_t data;
00065 m_container.readInt16(file, id);
00066 m_container.readInt16(file, type);
00067 m_container.readInt32(file, count);
00068 file->read(&data, 4);
00069 IFDEntry::Ref entry(new IFDEntry(id, type,
00070 count, data, m_container));
00071 Trace(DEBUG1) << "adding elem for " << id << "\n";
00072 m_entries[id] = entry;
00073 }
00074
00075 return true;
00076 }
00077
00078 IFDEntry::Ref IFDDir::getEntry(int id)
00079 {
00080 return m_entries[id];
00081 }
00082
00083
00084 bool IFDDir::getIntegerValue(int id, uint32_t &v)
00085 {
00086 bool success = false;
00087 IFDEntry::Ref e = getEntry(id);
00088 if (e != NULL) {
00089 try {
00090 switch(e->type())
00091 {
00092 case IFD::EXIF_FORMAT_LONG:
00093 v = e->getLong();
00094 success = true;
00095 break;
00096 case IFD::EXIF_FORMAT_SHORT:
00097 v = e->getShort();
00098 success = true;
00099 break;
00100 default:
00101 break;
00102 }
00103 }
00104 catch(std::exception & e) {
00105 Trace(ERROR) << "Exception raised " << e.what()
00106 << " fetch integer value for " << id << "\n";
00107 }
00108 }
00109 return success;
00110 }
00111
00112
00113 bool IFDDir::getLongValue(int id, uint32_t &v)
00114 {
00115 bool success = false;
00116 IFDEntry::Ref e = getEntry(id);
00117 if (e != NULL) {
00118 try {
00119 v = e->getLong();
00120 success = true;
00121 }
00122 catch(std::exception & e) {
00123 Trace(ERROR) << "Exception raised " << e.what()
00124 << " fetch long value for " << id << "\n";
00125 }
00126 }
00127 return success;
00128 }
00129
00130
00131 bool IFDDir::getShortValue(int id, uint16_t &v)
00132 {
00133 bool success = false;
00134 IFDEntry::Ref e = getEntry(id);
00135 if (e != NULL) {
00136 try {
00137 v = e->getShort();
00138 success = true;
00139 }
00140 catch(std::exception & e) {
00141 Trace(ERROR) << "Exception raised " << e.what()
00142 << " fetch long value for " << id << "\n";
00143 }
00144 }
00145 return success;
00146 }
00147
00148 off_t IFDDir::nextIFD()
00149 {
00150 int16_t numEntries;
00151 IO::Stream *file = m_container.file();
00152
00153 if(m_entries.size() == 0) {
00154 file->seek(m_offset, SEEK_SET);
00155 m_container.readInt16(file, numEntries);
00156 Trace(DEBUG1) << "numEntries =" << numEntries
00157 << " shifting " << (numEntries * 12) + 2
00158 << "bytes\n";
00159 }
00160 else {
00161 numEntries = m_entries.size();
00162 }
00163
00164 file->seek(m_offset + (numEntries * 12) + 2, SEEK_SET);
00165 int32_t next;
00166 m_container.readInt32(file, next);
00167 return next;
00168 }
00169
00173 IFDDir::Ref IFDDir::getSubIFD()
00174 {
00175 bool success;
00176 uint32_t offset = 0;
00177 success = getLongValue(IFD::EXIF_TAG_SUB_IFDS, offset);
00178 if (success) {
00179 Ref ref(new IFDDir(offset, m_container));
00180 }
00181 return Ref(static_cast<IFDDir*>(NULL));
00182 }
00183
00187 IFDDir::Ref IFDDir::getExifIFD()
00188 {
00189 bool success;
00190 uint32_t offset = 0;
00191 success = getLongValue(IFD::EXIF_TAG_EXIF_IFD_POINTER, offset);
00192 if (success) {
00193 Ref ref(new IFDDir(offset, m_container));
00194 }
00195 return Ref(static_cast<IFDDir*>(NULL));
00196 }
00197
00198 }
00199 }
00200