mrwcontainer.cpp

00001 /*
00002  * libopenraw - mrwcontainer.cpp
00003  *
00004  * Copyright (C) 2006 Hubert Figuiere
00005  * Copyright (C) 2008 Bradley Broom
00006  *
00007  * This library is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2.1 of the License, or (at your option) any later version.
00011  *
00012  * This library is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with this library; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
00020  */
00021 
00022 #include "debug.h"
00023 #include "mrwcontainer.h"
00024 #include "io/file.h"
00025 
00026 
00027 using namespace Debug;
00028 
00029 namespace OpenRaw {
00030 
00031     namespace Internals {
00032 
00033         namespace MRW {
00034 
00035             DataBlock::DataBlock(off_t start, MRWContainer * _container)
00036                 : m_start(start),
00037                   m_container(_container),
00038                   m_loaded(false)
00039             {
00040                 Trace(DEBUG2) << "> DataBlock start == " << start << "\n";
00041                 if (m_container->fetchData (m_name, m_start, 4) != 4) {
00042                     // FIXME: Handle error
00043                     Trace(WARNING) << "  Error reading block name " << start << "\n";
00044                     return;
00045                 }
00046                 if (!m_container->readInt32 (m_container->file(), m_length)) {
00047                     // FIXME: Handle error
00048                     Trace(WARNING) << "  Error reading block length " << start << "\n";
00049                     return;
00050                 }
00051                 Trace(DEBUG1) << "  DataBlock " << name() 
00052                               << ", length " << m_length 
00053                               << " at " << m_start << "\n";
00054                 Trace(DEBUG2) << "< DataBlock\n";
00055                 m_loaded = true;
00056             }
00057 
00058             int8_t DataBlock::int8_val (off_t off)
00059             {
00060                 int8_t ret;
00061                 MRWContainer *mc = m_container;
00062                 mc->file()->seek (m_start + DataBlockHeaderLength + off, SEEK_SET);
00063                 mc->readInt8 (mc->file(), ret);
00064                 return ret;
00065             }
00066             
00067             uint8_t DataBlock::uint8_val (off_t off)
00068             {
00069                 uint8_t ret;
00070                 MRWContainer *mc = m_container;
00071                 mc->file()->seek (m_start + DataBlockHeaderLength + off, SEEK_SET);
00072                 mc->readUInt8 (mc->file(), ret);
00073                 return ret;
00074             }
00075             
00076             uint16_t DataBlock::uint16_val (off_t off)
00077             {
00078                 uint16_t ret;
00079                 MRWContainer *mc = m_container;
00080                 mc->file()->seek (m_start + DataBlockHeaderLength + off, SEEK_SET);
00081                 mc->readUInt16 (mc->file(), ret);
00082                 return ret;
00083             }
00084             
00085         }
00086 
00087         MRWContainer::MRWContainer(IO::Stream *_file, off_t offset)
00088             : IFDFileContainer(_file, offset)
00089         {
00090 
00091         }
00092 
00093 
00094         MRWContainer::~MRWContainer()
00095         {
00096         }
00097 
00098 
00099         IFDFileContainer::EndianType 
00100         MRWContainer::isMagicHeader(const char *p, int len)
00101         {
00102             if (len < 4) {
00103                 // we need at least 4 bytes to check
00104                 return ENDIAN_NULL;
00105             }
00106 
00107             if ((p[0] == 0x00) && (p[1] == 'M') && 
00108                 (p[2] == 'R') && (p[3] == 'M')) {
00109 
00110                 Trace(DEBUG1) << "Identified MRW file\n";
00111 
00112                 return ENDIAN_BIG;
00113             }
00114 
00115             Trace(DEBUG1) << "Unidentified MRW file\n";
00116 
00117             return ENDIAN_NULL;
00118         }
00119 
00120         bool MRWContainer::locateDirsPreHook()
00121         {
00122             char version[9];
00123             off_t position;
00124 
00125             Trace(DEBUG1) << "> MRWContainer::locateDirsPreHook()\n";
00126             m_endian = ENDIAN_BIG;
00127             
00128             /* MRW file always starts with an MRM datablock. */
00129             mrm = MRW::DataBlock::Ref (new MRW::DataBlock (m_offset, this));
00130             if (mrm->name() != "MRM") {
00131                 Trace(WARNING) << "MRW file begins not with MRM block, "
00132                     "but with unrecognized DataBlock :: name == " 
00133                                << mrm->name() << "\n";
00134                 return false;
00135             }
00136 
00137             /* Subblocks are contained within the MRM block. Scan them and create
00138              * appropriate block descriptors.
00139              */
00140             position = mrm->offset() + MRW::DataBlockHeaderLength;
00141             while (position < pixelDataOffset()) {
00142                 MRW::DataBlock::Ref ref (new MRW::DataBlock (position, this));
00143                 Trace(DEBUG1) << "Loaded DataBlock :: name == " << ref->name() << "\n";
00144                 if(!ref || !ref->loaded()) {
00145                     break;
00146                 }
00147                 if (ref->name() == "PRD") {
00148                     if (prd != NULL) {
00149                         Trace(WARNING) << "File contains duplicate DataBlock :: name == " 
00150                                        << ref->name() << "\n";
00151                     }
00152                     prd = ref;
00153                 }
00154                 else if (ref->name() == "TTW") {
00155                     if (ttw != NULL) {
00156                         Trace(WARNING) << "File contains duplicate DataBlock :: name == " 
00157                                        << ref->name() << "\n";
00158                     }
00159                     ttw = ref;
00160                 }
00161                 else if (ref->name() == "WBG") {
00162                     if (wbg != NULL) {
00163                         Trace(WARNING) << "File contains duplicate DataBlock :: name == " 
00164                                        << ref->name() << "\n";
00165                     }
00166                     wbg = ref;
00167                 }
00168                 else if (ref->name() == "RIF") {
00169                     if (rif != NULL) {
00170                         Trace(WARNING) << "File contains duplicate DataBlock :: name == " 
00171                                        << ref->name() << "\n";
00172                     }
00173                     rif = ref;
00174                 }
00175                 else if (ref->name() != "PAD") {
00176                     Trace(WARNING) << "File contains unrecognized DataBlock :: name == " 
00177                                    << ref->name() << "\n";
00178                 }
00179                 position = ref->offset() + MRW::DataBlockHeaderLength + ref->length();
00180             }
00181 
00182             /* Check that we found all the expected data blocks. */
00183             if (prd == NULL) {
00184                 Trace(WARNING) << "File does NOT contain expected DataBlock :: name == PRD\n";
00185                 return false;
00186             }
00187             if (ttw == NULL) {
00188                 Trace(WARNING) << "File does NOT contain expected DataBlock :: name == TTW\n";
00189                 return false;
00190             }
00191             if (wbg == NULL) {
00192                 Trace(WARNING) << "File does NOT contain expected DataBlock :: name == WBG\n";
00193                 return false;
00194             }
00195             if (rif == NULL) {
00196                 Trace(WARNING) << "File does NOT contain expected DataBlock :: name == RIF\n";
00197                 return false;
00198             }
00199 
00200             /* Extract the file version string. */
00201             if (fetchData (version, prd->offset()+MRW::DataBlockHeaderLength+MRW::PRD_VERSION, 8) != 8) {
00202                 // FIXME: Handle error
00203                 Debug::Trace(DEBUG1) << "  Error reading version string\n";
00204             }
00205             version[8] = '\0';
00206             m_version = std::string (version);
00207             Trace(DEBUG1) << "  MRW file version == " << m_version << "\n";
00208 
00209             /* For the benefit of our parent class, set the container offset to the beginning of
00210              * the TIFF data (the contents of the TTW data block), and seek there.
00211              */
00212             m_offset = ttw->offset() + MRW::DataBlockHeaderLength;
00213             if((version[2] != '7') || (version[3] != '3')) {
00214                 setExifOffsetCorrection(m_offset);
00215                 Trace(DEBUG1) << "setting correction to " << m_offset << "\n";
00216             }
00217             m_file->seek (m_offset, SEEK_SET);
00218             Trace(DEBUG1) << "< MRWContainer\n";
00219             
00220             return true;
00221         }
00222 
00223     }
00224 }

Generated on Sun Mar 23 09:30:49 2008 for libopenraw by  doxygen 1.5.5