00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <sys/types.h>
00022
00023 #include <cstdlib>
00024 #include <cstdio>
00025 #include <vector>
00026 #include <iostream>
00027
00028 #include "debug.h"
00029
00030 #include "ifdfilecontainer.h"
00031 #include "io/file.h"
00032
00033
00034 using namespace Debug;
00035
00036 namespace OpenRaw {
00037
00038 namespace Internals {
00039
00040 IFDFileContainer::IFDFileContainer(IO::Stream *_file, off_t offset)
00041 : RawContainer(_file, offset),
00042 m_error(0),
00043 m_exif_offset_correction(0),
00044 m_current_dir(),
00045 m_dirs()
00046 {
00047 }
00048
00049 IFDFileContainer::~IFDFileContainer()
00050 {
00051 m_dirs.clear();
00052 }
00053
00054
00055 IFDFileContainer::EndianType
00056 IFDFileContainer::isMagicHeader(const char *p, int len)
00057 {
00058 if (len < 4){
00059
00060 return ENDIAN_NULL;
00061 }
00062 if ((p[0] == 0x49) && (p[1] == 0x49)
00063 && (p[2] == 0x2a) && (p[3] == 0x00)) {
00064 return ENDIAN_LITTLE;
00065 }
00066 else if ((p[0] == 0x4d) && (p[1] == 0x4d)
00067 && (p[2] == 0x00) && (p[3] == 0x2a)) {
00068 return ENDIAN_BIG;
00069 }
00070 return ENDIAN_NULL;
00071 }
00072
00073
00074 int IFDFileContainer::countDirectories(void)
00075 {
00076 if (m_dirs.size() == 0) {
00077
00078 bool ret = _locateDirs();
00079 if (!ret) {
00080 return -1;
00081 }
00082 }
00083 return m_dirs.size();
00084 }
00085
00086 std::vector<IFDDir::Ref> &
00087 IFDFileContainer::directories()
00088 {
00089 if (m_dirs.size() == 0) {
00090 countDirectories();
00091 }
00092 return m_dirs;
00093 }
00094
00095 IFDDir::Ref
00096 IFDFileContainer::setDirectory(int dir)
00097 {
00098 if (dir < 0) {
00099
00100 return IFDDir::Ref((IFDDir*)NULL);
00101 }
00102
00103 int n = countDirectories();
00104 if (n <= 0) {
00105
00106 return IFDDir::Ref((IFDDir*)NULL);
00107 }
00108
00109
00110 if (dir > (int)m_dirs.size()) {
00111
00112 return IFDDir::Ref((IFDDir*)NULL);
00113 }
00114 m_current_dir = m_dirs[dir];
00115 m_current_dir->load();
00116 return m_current_dir;
00117 }
00118
00119
00120 size_t
00121 IFDFileContainer::getDirectoryDataSize()
00122 {
00123
00124 Trace(DEBUG1) << "getDirectoryDataSize()" << "\n";
00125 off_t offset = m_current_dir->offset();
00126
00127 Trace(DEBUG1) << "offset = " << offset
00128 << " m_numTags = " << m_current_dir->numTags() << "\n";
00129 off_t begin = offset + 2 + (m_current_dir->numTags()*12);
00130
00131 Trace(DEBUG1) << "begin = " << begin << "\n";
00132
00133 m_file->seek(begin, SEEK_SET);
00134 begin += 2;
00135 int32_t nextIFD;
00136 readInt32(m_file, nextIFD);
00137 Trace(DEBUG1) << "nextIFD = " << nextIFD << "\n";
00138 if (nextIFD == 0) {
00139
00140 }
00141 return nextIFD - begin;
00142 }
00143
00144 bool IFDFileContainer::locateDirsPreHook()
00145 {
00146 return true;
00147 }
00148
00149
00150 bool
00151 IFDFileContainer::_locateDirs(void)
00152 {
00153 if(!locateDirsPreHook()) {
00154 return false;
00155 }
00156 Trace(DEBUG1) << "_locateDirs()\n";
00157 if (m_endian == ENDIAN_NULL) {
00158 char buf[4];
00159 m_file->seek(m_offset, SEEK_SET);
00160 m_file->read(buf, 4);
00161 m_endian = isMagicHeader(buf, 4);
00162 if (m_endian == ENDIAN_NULL) {
00163
00164 return false;
00165 }
00166 }
00167 m_file->seek(m_offset + 4, SEEK_SET);
00168 int32_t offset = 0;
00169 readInt32(m_file, offset);
00170 m_dirs.clear();
00171 do {
00172 if (offset != 0) {
00173
00174 Trace(DEBUG1) << "push offset =0x" << offset << "\n";
00175
00176
00177
00178 IFDDir::Ref dir(new IFDDir(m_offset + offset,*this));
00179 m_dirs.push_back(dir);
00180
00181
00182
00183 offset = dir->nextIFD();
00184 }
00185 } while(offset != 0);
00186
00187 Trace(DEBUG1) << "# dir found = " << m_dirs.size() << "\n";
00188 return (m_dirs.size() != 0);
00189 }
00190
00191
00192 }
00193 }
00194