ciffcontainer.cpp

00001 /*
00002  * libopenraw - ciffcontainer.cpp
00003  *
00004  * Copyright (C) 2006-2008 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 License
00008  * as published by the Free Software Foundation, either version 3 of
00009  * 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, see
00018  * <http://www.gnu.org/licenses/>.
00019  */
00020 
00021 #include <cstring>
00022 #include <iostream>
00023 #include <boost/shared_ptr.hpp>
00024 
00025 #include <libopenraw/types.h>
00026 
00027 #include "io/file.h"
00028 #include "ciffcontainer.h"
00029 #include "debug.h"
00030 
00031 using namespace Debug;
00032 
00033 namespace OpenRaw {
00034     namespace Internals {
00035 
00036         namespace CIFF {
00037 
00038 
00039             bool ImageSpec::readFrom(off_t offset, CIFFContainer *container)
00040             {
00041                 bool ret;
00042                 IO::Stream *file = container->file();
00043                 file->seek(offset, SEEK_SET);
00044                 ret = container->readUInt32(file, imageWidth);
00045                 ret = container->readUInt32(file, imageHeight);
00046                 ret = container->readUInt32(file, pixelAspectRatio);
00047                 ret = container->readInt32(file, rotationAngle);
00048                 ret = container->readUInt32(file, componentBitDepth);
00049                 ret = container->readUInt32(file, colorBitDepth);
00050                 ret = container->readUInt32(file, colorBW);
00051                 return ret;
00052             }
00053 
00054             int32_t ImageSpec::exifOrientation() const
00055             {
00056                 int32_t orientation = 0;
00057                 switch(rotationAngle) {
00058                 case 0:
00059                     orientation = 1;
00060                     break;
00061                 case 90:
00062                     orientation = 6;
00063                     break;
00064                 case 180:
00065                     orientation = 3;
00066                     break;
00067                 case 270:
00068                     orientation = 8;
00069                     break;
00070                 }
00071                 return orientation;
00072             }
00073 
00074             RecordEntry::RecordEntry()
00075                 : typeCode(0), length(0), offset(0)
00076             {
00077             }
00078 
00079             bool RecordEntry::readFrom(CIFFContainer *container)
00080             {
00081                 bool ret;
00082                 IO::Stream *file = container->file();
00083                 ret = container->readUInt16(file, typeCode);
00084                 ret = container->readUInt32(file, length);
00085                 ret = container->readUInt32(file, offset);
00086                 return ret;
00087             }
00088 
00089             size_t RecordEntry::fetchData(Heap* heap, void* buf, size_t size) const
00090             {
00091                 return heap->container()->fetchData(buf, 
00092                                                     offset + heap->offset(), size);
00093             }
00094 
00095 
00096             Heap::Heap(off_t start, off_t length, CIFFContainer * _container)
00097                 : m_start(start),
00098                     m_length(length),
00099                     m_container(_container),
00100                     m_records()
00101             {
00102                 Debug::Trace(DEBUG2) << "Heap @ " << start << " length = "
00103                                                          << m_length << "\n";
00104             }
00105 
00106             std::vector<RecordEntry> & Heap::records()
00107             {
00108                 if (m_records.size() == 0) {
00109                     _loadRecords();
00110                 }
00111                 return m_records;
00112             }
00113 
00114 
00115             bool Heap::_loadRecords()
00116             {
00117                 IO::Stream *file = m_container->file();
00118                 file->seek(m_start + m_length - 4, SEEK_SET);
00119                 int32_t record_offset;
00120                 bool ret = m_container->readInt32(file, record_offset);
00121                     
00122                 if (ret) {
00123                     int16_t numRecords;
00124 
00125                     m_records.clear();
00126                     file->seek(m_start + record_offset, SEEK_SET);
00127                     ret = m_container->readInt16(file, numRecords);
00128                     if (!ret) 
00129                     {
00130                         Trace(DEBUG1) << "read failed: " << ret << "\n";
00131                     }
00132                     Trace(DEBUG2) << "numRecords " << numRecords << "\n";
00133                     int16_t i;
00134                     m_records.reserve(numRecords);
00135                     for (i = 0; i < numRecords; i++) {
00136                         m_records.push_back(RecordEntry());
00137                         m_records.back().readFrom(m_container);
00138                     }
00139                 }
00140                 return ret;
00141             }
00142 
00143 
00144 #if 0
00145             class OffsetTable {
00146                 uint16_t numRecords;/* the number tblArray elements */
00147                 RecordEntry tblArray[1];/* Array of the record entries */
00148             };
00149 #endif
00150 
00151 
00152             bool HeapFileHeader::readFrom(CIFFContainer *container)
00153             {
00154                 endian = RawContainer::ENDIAN_NULL;
00155                 bool ret = false;
00156                 IO::Stream *file = container->file();
00157                 int s = file->read(byteOrder, 2);
00158                 if (s == 2) {
00159                     if((byteOrder[0] == 'I') && (byteOrder[1] == 'I')) {
00160                         endian = RawContainer::ENDIAN_LITTLE;
00161                     }
00162                     else if((byteOrder[0] == 'M') && (byteOrder[1] == 'M')) {
00163                         endian = RawContainer::ENDIAN_BIG;
00164                     }
00165                     container->setEndian(endian);
00166                     ret = container->readUInt32(file, headerLength);
00167                     if (ret) {
00168                         ret = (file->read(type, 4) == 4);
00169                     }
00170                     if (ret) {
00171                         ret = (file->read(subType, 4) == 4);
00172                     }
00173                     if (ret) {
00174                         ret = container->readUInt32(file, version);
00175                     }
00176                 }
00177                 return ret;
00178             }
00179         }
00180         
00181         CIFFContainer::CIFFContainer(IO::Stream *_file)
00182             : RawContainer(_file, 0),
00183               m_hdr(),
00184               m_heap((CIFF::Heap*)NULL),
00185               m_hasImageSpec(false)
00186         {
00187             m_endian = _readHeader();
00188         }
00189 
00190         CIFFContainer::~CIFFContainer()
00191         {
00192         }
00193 
00194         CIFF::Heap::Ref CIFFContainer::heap()
00195         {
00196             if (m_heap == NULL) {
00197                 _loadHeap();
00198             }
00199             return m_heap;
00200         }
00201 
00202         bool CIFFContainer::_loadHeap()
00203         {
00204             bool ret = false;
00205             if (m_heap == NULL) {
00206                 if(m_endian != ENDIAN_NULL) {
00207                     off_t heapLength = m_file->filesize() - m_hdr.headerLength;
00208 
00209                     Trace(DEBUG1) << "heap len " << heapLength << "\n";
00210                     m_heap = CIFF::Heap::Ref(new CIFF::Heap(m_hdr.headerLength, 
00211                                                                                                     heapLength, this));
00212                     
00213                     ret = true;
00214                 }
00215                 else {
00216                     Trace(DEBUG1) << "Unknown endian\n";
00217                 }
00218             }
00219             return ret;
00220         }
00221 
00222 
00223         RawContainer::EndianType CIFFContainer::_readHeader()
00224         {
00225             EndianType _endian = ENDIAN_NULL;
00226             m_hdr.readFrom(this);
00227             if ((::strncmp(m_hdr.type, "HEAP", 4) == 0)
00228                     && (::strncmp(m_hdr.subType, "CCDR", 4) == 0)) {
00229                 _endian = m_hdr.endian;
00230             }
00231             return _endian;
00232         }
00233 
00234         CIFF::Heap::Ref CIFFContainer::getImageProps()
00235         {
00236             if(!m_imageprops) {
00237                 if(!heap()) {
00238                     return CIFF::Heap::Ref();
00239                 }
00240                 
00241                 const CIFF::RecordEntry::List & records = m_heap->records();
00242                 CIFF::RecordEntry::List::const_iterator iter;
00243                 
00244                 // locate the properties
00245                 iter = std::find_if(records.begin(), records.end(), boost::bind(
00246                                         &CIFF::RecordEntry::isA, _1, 
00247                                         static_cast<uint16_t>(CIFF::TAG_IMAGEPROPS)));
00248                 if (iter == records.end()) {
00249                     Trace(ERROR) << "Couldn't find the image properties.\n";
00250                     return CIFF::Heap::Ref();
00251                 }
00252                 
00253                 m_imageprops = CIFF::Heap::Ref(new CIFF::Heap(iter->offset + m_heap->offset(), iter->length, this));
00254             }
00255             return m_imageprops;
00256         }
00257         
00258         const CIFF::ImageSpec * CIFFContainer::getImageSpec()
00259         {
00260             if(!m_hasImageSpec) {
00261                 CIFF::Heap::Ref props = getImageProps();
00262 
00263                 if(!props)
00264                     return NULL;
00265                 const CIFF::RecordEntry::List & propsRecs = props->records();
00266                 CIFF::RecordEntry::List::const_iterator iter;
00267                 iter = std::find_if(propsRecs.begin(), propsRecs.end(), 
00268                                     boost::bind(
00269                                         &CIFF::RecordEntry::isA, _1, 
00270                                         static_cast<uint16_t>(CIFF::TAG_IMAGEINFO)));
00271                 if (iter == propsRecs.end()) {
00272                     Trace(ERROR) << "Couldn't find the image info.\n";
00273                     return NULL;
00274                 }
00275                 m_imagespec.readFrom(iter->offset + props->offset(), this);
00276                 m_hasImageSpec = true;
00277             }
00278             return &m_imagespec;
00279         }
00280 
00281 
00282         const CIFF::Heap::Ref CIFFContainer::getCameraProps()
00283         {
00284             if(!m_cameraprops) {
00285                 CIFF::Heap::Ref props = getImageProps();
00286 
00287                 if(!props)
00288                     return CIFF::Heap::Ref();
00289                 const CIFF::RecordEntry::List & propsRecs = props->records();
00290                 CIFF::RecordEntry::List::const_iterator iter;
00291                 iter = std::find_if(propsRecs.begin(), propsRecs.end(), 
00292                                     boost::bind(
00293                                         &CIFF::RecordEntry::isA, _1, 
00294                                         static_cast<uint16_t>(CIFF::TAG_CAMERAOBJECT)));
00295                 if (iter == propsRecs.end()) {
00296                     Trace(ERROR) << "Couldn't find the camera props.\n";
00297                     return CIFF::Heap::Ref();
00298                 }
00299                 m_cameraprops = CIFF::Heap::Ref(new CIFF::Heap(iter->offset + props->offset(),
00300                                                                iter->length, this));
00301             }
00302             return m_cameraprops;
00303         }
00304 
00305         const CIFF::RecordEntry * CIFFContainer::getRawDataRecord() const
00306         {
00307             if(!m_heap) {
00308                 return NULL;
00309             }
00310             const CIFF::RecordEntry::List & records = m_heap->records();
00311             CIFF::RecordEntry::List::const_iterator iter;
00312             // locate the RAW data
00313             iter = std::find_if(records.begin(), records.end(), boost::bind(
00314                                     &CIFF::RecordEntry::isA, _1, 
00315                                     static_cast<uint16_t>(CIFF::TAG_RAWIMAGEDATA)));
00316             
00317             if (iter != records.end()) {
00318                 return &(*iter);
00319             }
00320             return NULL;
00321         }
00322     }
00323 }

Generated on Wed Aug 25 01:26:34 2010 for libopenraw by  doxygen 1.5.9