ifdfilecontainer.cpp

00001 /*
00002  * libopenraw - ifdfilecontainer.cpp
00003  *
00004  * Copyright (C) 2006 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
00008  * License as published by the Free Software Foundation; either
00009  * version 2.1 of 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, write to the Free Software
00018  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
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_current_dir(),
00044                 m_dirs()
00045         {
00046         }
00047     
00048         IFDFileContainer::~IFDFileContainer()
00049         {
00050             m_dirs.clear();
00051         }
00052 
00053 
00054         IFDFileContainer::EndianType 
00055         IFDFileContainer::isMagicHeader(const char *p, int len)
00056         {
00057             if (len < 4){
00058                 // we need at least 4 bytes to check
00059                 return ENDIAN_NULL;
00060             }
00061             if ((p[0] == 0x49) && (p[1] == 0x49)
00062                     && (p[2] == 0x2a) && (p[3] == 0x00)) {
00063                 return ENDIAN_LITTLE;
00064             }
00065             else if ((p[0] == 0x4d) && (p[1] == 0x4d)
00066                              && (p[2] == 0x00) && (p[3] == 0x2a)) {
00067                 return ENDIAN_BIG;
00068             }
00069             return ENDIAN_NULL;
00070         }
00071 
00072 
00073         int IFDFileContainer::countDirectories(void)
00074         {
00075             if (m_dirs.size() == 0) {
00076                 // FIXME check result
00077                 bool ret = _locateDirs();
00078                 if (!ret) {
00079                     return -1;
00080                 }
00081             }
00082             return m_dirs.size();
00083         }
00084 
00085         std::vector<IFDDir::Ref> & 
00086         IFDFileContainer::directories()
00087         {
00088             if (m_dirs.size() == 0) {
00089                 countDirectories();
00090             }
00091             return m_dirs;
00092         }
00093 
00094         IFDDir::Ref
00095         IFDFileContainer::setDirectory(int dir)
00096         {
00097             if (dir < 0) {
00098                 // FIXME set error
00099                 return IFDDir::Ref((IFDDir*)NULL);
00100             }
00101             // FIXME handle negative values
00102             int n = countDirectories();
00103             if (n <= 0) {
00104                 // FIXME set error
00105                 return IFDDir::Ref((IFDDir*)NULL);
00106             }
00107             // dir is signed here because we can pass negative 
00108             // value for specific Exif IFDs.
00109             if (dir > (int)m_dirs.size()) {
00110                 // FIXME set error
00111                 return IFDDir::Ref((IFDDir*)NULL);
00112             }
00113             m_current_dir = m_dirs[dir];
00114             m_current_dir->load();
00115             return m_current_dir;
00116         }
00117 
00118 
00119         size_t 
00120         IFDFileContainer::getDirectoryDataSize()
00121         {
00122             // TODO move to IFDirectory
00123             Trace(DEBUG1) << "getDirectoryDataSize()" << "\n";
00124             off_t offset = m_current_dir->offset();
00125             // FIXME check error
00126             Trace(DEBUG1) << "offset = " << offset 
00127                                 << " m_numTags = " << m_current_dir->numTags() << "\n";
00128             off_t begin = offset + 2 + (m_current_dir->numTags()*12);
00129             
00130             Trace(DEBUG1) << "begin = " << begin << "\n";
00131 
00132             m_file->seek(begin, SEEK_SET);
00133             begin += 2;
00134             int32_t nextIFD;
00135             readInt32(m_file, nextIFD);
00136             Trace(DEBUG1) << "nextIFD = " << nextIFD << "\n";
00137             if (nextIFD == 0) {
00138                 // FIXME not good
00139             }
00140             return nextIFD - begin;
00141         }
00142 
00143 
00144         bool
00145         IFDFileContainer::_locateDirs(void)
00146         {
00147             Trace(DEBUG1) << "_locateDirs()\n";
00148             if (m_endian == ENDIAN_NULL) {
00149                 char buf[4];
00150                 m_file->read(buf, 4);
00151                 m_endian = isMagicHeader(buf, 4);
00152                 if (m_endian == ENDIAN_NULL) {
00153                     // FIXME set error code
00154                     return false;
00155                 }
00156             }
00157             m_file->seek(4, SEEK_SET);
00158             int32_t offset = 0;
00159             readInt32(m_file, offset);
00160             m_dirs.clear();
00161             do {
00162                 if (offset != 0) {
00163 //                  std::cerr.setf(std::ios_base::hex, std::ios_base::basefield);
00164                     Trace(DEBUG1) << "push offset =0x" << offset << "\n";
00165 
00166                     IFDDir::Ref dir(new IFDDir(offset,*this));
00167                     m_dirs.push_back(dir);
00168 
00169 //                  std::cerr.setf((std::ios_base::fmtflags)0, std::ios_base::basefield);
00170 
00171                     offset = dir->nextIFD();
00172                 }
00173             } while(offset != 0);
00174 
00175             Trace(DEBUG1) << "# dir found = " << m_dirs.size() << "\n";
00176             return (m_dirs.size() != 0);
00177         }
00178 
00179 
00180     }
00181 }
00182 

Generated on Sat Jan 27 11:36:13 2007 for libopenraw by  doxygen 1.4.7