00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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
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 }