libopenraw
|
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 License 00009 * as published by the Free Software Foundation, either version 3 of 00010 * 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, see 00019 * <http://www.gnu.org/licenses/>. 00020 */ 00021 00022 #include "trace.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 std::string DataBlock::string_val(off_t off) 00086 { 00087 char buf[9]; 00088 size_t s; 00089 MRWContainer *mc = m_container; 00090 s = mc->fetchData(buf, m_start + DataBlockHeaderLength + off, 8); 00091 if(s == 8) { 00092 buf[8] = 0; 00093 } 00094 else { 00095 *buf = 0; 00096 } 00097 return buf; 00098 } 00099 } 00100 00101 MRWContainer::MRWContainer(IO::Stream *_file, off_t offset) 00102 : IFDFileContainer(_file, offset) 00103 { 00104 00105 } 00106 00107 00108 MRWContainer::~MRWContainer() 00109 { 00110 } 00111 00112 00113 IFDFileContainer::EndianType 00114 MRWContainer::isMagicHeader(const char *p, int len) 00115 { 00116 if (len < 4) { 00117 // we need at least 4 bytes to check 00118 return ENDIAN_NULL; 00119 } 00120 00121 if ((p[0] == 0x00) && (p[1] == 'M') && 00122 (p[2] == 'R') && (p[3] == 'M')) { 00123 00124 Trace(DEBUG1) << "Identified MRW file\n"; 00125 00126 return ENDIAN_BIG; 00127 } 00128 00129 Trace(DEBUG1) << "Unidentified MRW file\n"; 00130 00131 return ENDIAN_NULL; 00132 } 00133 00134 bool MRWContainer::locateDirsPreHook() 00135 { 00136 char version[9]; 00137 off_t position; 00138 00139 Trace(DEBUG1) << "> MRWContainer::locateDirsPreHook()\n"; 00140 m_endian = ENDIAN_BIG; 00141 00142 /* MRW file always starts with an MRM datablock. */ 00143 mrm = MRW::DataBlock::Ref (new MRW::DataBlock (m_offset, this)); 00144 if (mrm->name() != "MRM") { 00145 Trace(WARNING) << "MRW file begins not with MRM block, " 00146 "but with unrecognized DataBlock :: name == " 00147 << mrm->name() << "\n"; 00148 return false; 00149 } 00150 00151 /* Subblocks are contained within the MRM block. Scan them and create 00152 * appropriate block descriptors. 00153 */ 00154 position = mrm->offset() + MRW::DataBlockHeaderLength; 00155 while (position < pixelDataOffset()) { 00156 MRW::DataBlock::Ref ref (new MRW::DataBlock (position, this)); 00157 Trace(DEBUG1) << "Loaded DataBlock :: name == " << ref->name() << "\n"; 00158 if(!ref || !ref->loaded()) { 00159 break; 00160 } 00161 if (ref->name() == "PRD") { 00162 if (prd != NULL) { 00163 Trace(WARNING) << "File contains duplicate DataBlock :: name == " 00164 << ref->name() << "\n"; 00165 } 00166 prd = ref; 00167 } 00168 else if (ref->name() == "TTW") { 00169 if (ttw != NULL) { 00170 Trace(WARNING) << "File contains duplicate DataBlock :: name == " 00171 << ref->name() << "\n"; 00172 } 00173 ttw = ref; 00174 } 00175 else if (ref->name() == "WBG") { 00176 if (wbg != NULL) { 00177 Trace(WARNING) << "File contains duplicate DataBlock :: name == " 00178 << ref->name() << "\n"; 00179 } 00180 wbg = ref; 00181 } 00182 else if (ref->name() == "RIF") { 00183 if (rif != NULL) { 00184 Trace(WARNING) << "File contains duplicate DataBlock :: name == " 00185 << ref->name() << "\n"; 00186 } 00187 rif = ref; 00188 } 00189 else if (ref->name() != "PAD") { 00190 Trace(WARNING) << "File contains unrecognized DataBlock :: name == " 00191 << ref->name() << "\n"; 00192 } 00193 position = ref->offset() + MRW::DataBlockHeaderLength + ref->length(); 00194 } 00195 00196 /* Check that we found all the expected data blocks. */ 00197 if (prd == NULL) { 00198 Trace(WARNING) << "File does NOT contain expected DataBlock :: name == PRD\n"; 00199 return false; 00200 } 00201 if (ttw == NULL) { 00202 Trace(WARNING) << "File does NOT contain expected DataBlock :: name == TTW\n"; 00203 return false; 00204 } 00205 if (wbg == NULL) { 00206 Trace(WARNING) << "File does NOT contain expected DataBlock :: name == WBG\n"; 00207 return false; 00208 } 00209 if (rif == NULL) { 00210 Trace(WARNING) << "File does NOT contain expected DataBlock :: name == RIF\n"; 00211 return false; 00212 } 00213 00214 /* Extract the file version string. */ 00215 if (fetchData (version, prd->offset()+MRW::DataBlockHeaderLength+MRW::PRD_VERSION, 8) != 8) { 00216 // FIXME: Handle error 00217 Debug::Trace(DEBUG1) << " Error reading version string\n"; 00218 } 00219 version[8] = '\0'; 00220 m_version = std::string (version); 00221 Trace(DEBUG1) << " MRW file version == " << m_version << "\n"; 00222 00223 /* For the benefit of our parent class, set the container offset to the beginning of 00224 * the TIFF data (the contents of the TTW data block), and seek there. 00225 */ 00226 m_offset = ttw->offset() + MRW::DataBlockHeaderLength; 00227 if((version[2] != '7') || (version[3] != '3')) { 00228 setExifOffsetCorrection(m_offset); 00229 Trace(DEBUG1) << "setting correction to " << m_offset << "\n"; 00230 } 00231 m_file->seek (m_offset, SEEK_SET); 00232 Trace(DEBUG1) << "< MRWContainer\n"; 00233 00234 return true; 00235 } 00236 00237 } 00238 }