ifdfile.cpp

00001 /*
00002  * libopenraw - ifdfile.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 <libopenraw++/thumbnail.h>
00022 
00023 #include "debug.h"
00024 #include "io/stream.h"
00025 #include "io/streamclone.h"
00026 #include "io/file.h"
00027 #include "ifd.h"
00028 #include "ifdfile.h"
00029 #include "ifdfilecontainer.h"
00030 #include "jfifcontainer.h"
00031 
00032 using namespace Debug;
00033 
00034 namespace OpenRaw {
00035     namespace Internals {
00036 
00037 
00038         IFDFile::IFDFile(const char *_filename, Type _type)
00039             : RawFile(_filename, _type),
00040                 m_thumbLocations(),
00041                 m_io(new IO::File(_filename)),
00042                 m_container(new IFDFileContainer(m_io, 0))
00043         {
00044 
00045         }
00046 
00047         IFDFile::~IFDFile()
00048         {
00049             delete m_container;
00050             delete m_io;
00051         }
00052 
00053         ::or_error IFDFile::_enumThumbnailSizes(std::vector<uint32_t> &list)
00054         {
00055             ::or_error err = OR_ERROR_NONE;
00056 
00057             Trace(DEBUG1) << "_enumThumbnailSizes()\n";
00058             std::vector<IFDDir::Ref> & dirs = m_container->directories();
00059             std::vector<IFDDir::Ref>::iterator iter; 
00060             
00061             Trace(DEBUG1) << "num of dirs " << dirs.size() << "\n";
00062             int c = 0;
00063             for(iter = dirs.begin(); iter != dirs.end(); ++iter, ++c)
00064             {
00065                 IFDDir::Ref & dir = *iter;
00066                 dir->load();
00067                 or_error ret = _locateThumbnail(dir, list);
00068                 if (ret == OR_ERROR_NONE)
00069                 {
00070                     Trace(DEBUG1) << "Found " << list.back() << " pixels\n";
00071                 }
00072             }
00073             if (list.size() <= 0) {
00074                 err = OR_ERROR_NOT_FOUND;
00075             }
00076             return err;
00077         }
00078 
00079 
00080         ::or_error IFDFile::_locateThumbnail(const IFDDir::Ref & dir,
00081                                                                      std::vector<uint32_t> &list)
00082         {
00083             ::or_error ret = OR_ERROR_NOT_FOUND;
00084             bool got_it;
00085             uint32_t x = 0;
00086             uint32_t y = 0;
00087             ::or_data_type type = OR_DATA_TYPE_NONE;
00088             uint32_t subtype = 0;
00089 
00090             Trace(DEBUG1) << "_locateThumbnail\n";
00091 
00092             got_it = dir->getLongValue(IFD::EXIF_TAG_NEW_SUBFILE_TYPE, subtype);
00093             Trace(DEBUG1) << "subtype " << subtype  << "\n";
00094             if (!got_it || (subtype == 1)) {
00095 
00096                 uint16_t photom_int = 0;
00097                 got_it = dir->getShortValue(IFD::EXIF_TAG_PHOTOMETRIC_INTERPRETATION, 
00098                                                                         photom_int);
00099 
00100                 if (got_it) {
00101                     Trace(DEBUG1) << "photometric int " << photom_int  << "\n";
00102                 }
00103                 // photometric interpretation is RGB
00104                 if (!got_it || (photom_int == 2)) {
00105 
00106                     got_it = dir->getIntegerValue(IFD::EXIF_TAG_IMAGE_WIDTH, x);
00107                     got_it = dir->getIntegerValue(IFD::EXIF_TAG_IMAGE_LENGTH, y);
00108 
00109                     uint32_t offset = 0;
00110                     got_it = dir->getLongValue(IFD::EXIF_TAG_STRIP_OFFSETS, offset);
00111                     if (!got_it) {
00112                         got_it = dir->getLongValue(IFD::EXIF_TAG_JPEG_INTERCHANGE_FORMAT,
00113                                                                              offset);
00114                         Trace(DEBUG1) << "looking for JPEG at " << offset << "\n";
00115                         if (got_it) {
00116                             type = OR_DATA_TYPE_JPEG;
00117                             if (x == 0 || y == 0) {
00118                                 IO::StreamClone *s = new IO::StreamClone(m_io, offset);
00119                                 JFIFContainer *jfif = new JFIFContainer(s, 0);
00120                                 if (jfif->getDimensions(x,y)) {
00121                                     Trace(DEBUG1) << "JPEG dimensions x=" << x 
00122                                                                 << " y=" << y << "\n";
00123                                 }
00124                                 else {
00125                                     type = OR_DATA_TYPE_NONE;
00126                                 }
00127                                 delete jfif;
00128                                 delete s;
00129                             }
00130                         }
00131                     }
00132                     else {
00133                         Trace(DEBUG1) << "found strip offsets\n";
00134                         if (x != 0 && y != 0) {
00135                             type = OR_DATA_TYPE_PIXMAP_8RGB;
00136                         }
00137                     }
00138                     if(type != OR_DATA_TYPE_NONE) {
00139                         uint32_t dim = std::max(x, y);
00140                         m_thumbLocations[dim] = IFDThumbDesc(x, y, type, dir);
00141                         list.push_back(dim);
00142                         ret = OR_ERROR_NONE;
00143                     }
00144                 }
00145             }
00146 
00147             return ret;
00148         }
00149 
00150 
00151         ::or_error IFDFile::_getThumbnail(uint32_t size, Thumbnail & thumbnail)
00152         {
00153             ::or_error ret = OR_ERROR_NOT_FOUND;
00154             ThumbLocations::iterator iter = m_thumbLocations.find(size);
00155             if(iter != m_thumbLocations.end()) 
00156             {
00157                 bool got_it;
00158 
00159                 IFDThumbDesc & desc = iter->second;
00160                 thumbnail.setDataType(desc.type);
00161                 uint32_t byte_length= 0; 
00162                 uint32_t offset = 0;
00163                 uint32_t x = desc.x;
00164                 uint32_t y = desc.y;
00165 
00166                 switch(desc.type)
00167                 {
00168                 case OR_DATA_TYPE_JPEG:
00169                     got_it = desc.ifddir
00170                         ->getLongValue(IFD::EXIF_TAG_JPEG_INTERCHANGE_FORMAT_LENGTH,
00171                                                      byte_length);
00172                     got_it = desc.ifddir
00173                         ->getLongValue(IFD::EXIF_TAG_JPEG_INTERCHANGE_FORMAT,
00174                                                      offset);
00175                     break;
00176                 case OR_DATA_TYPE_PIXMAP_8RGB:
00177                     got_it = desc.ifddir
00178                         ->getLongValue(IFD::EXIF_TAG_STRIP_OFFSETS, offset);
00179                     got_it = desc.ifddir
00180                         ->getLongValue(IFD::EXIF_TAG_STRIP_BYTE_COUNTS, byte_length);
00181 
00182                     got_it = desc.ifddir
00183                         ->getIntegerValue(IFD::EXIF_TAG_IMAGE_WIDTH, x);
00184                     got_it = desc.ifddir
00185                         ->getIntegerValue(IFD::EXIF_TAG_IMAGE_LENGTH, y);
00186                     break;
00187                 default:
00188                     break;
00189                 }
00190                 if (byte_length != 0) {
00191                     void *p = thumbnail.allocData(byte_length);
00192                     size_t real_size = m_container->fetchData(p, offset, 
00193                                                                                                         byte_length);
00194                     if (real_size < byte_length) {
00195                         Trace(WARNING) << "Size mismatch for data: ignoring.\n";
00196                     }
00197 
00198                     thumbnail.setDimensions(x, y);
00199                     ret = OR_ERROR_NONE;
00200                 }
00201             }
00202 
00203             return ret;
00204         }
00205 
00206     }
00207 }

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