00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041 #include <stdlib.h>
00042 #include <stdio.h>
00043
00044 #include "OSGConfig.h"
00045
00046 #include <OSGLog.h>
00047 #include <OSGBaseTypes.h>
00048 #include <OSGPathHandler.h>
00049 #include <OSGBaseFunctions.h>
00050 #include <OSGFileSystem.h>
00051 #include <OSGSceneFileHandler.h>
00052
00053 #include "OSGImageFileHandler.h"
00054
00055
00056 OSG_USING_NAMESPACE
00057
00071
00072
00073
00074
00075
00076
00077 ImageFileHandler *ImageFileHandler::_the = 0;
00078 const std::string ImageFileHandler::_fileNameKey("fileName");
00079 const std::string ImageFileHandler::_fullFilePathKey("fullFilePath");
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00094 ImageFileType *ImageFileHandler::getFileType(const char *mimeType,
00095 const char *fileName,
00096 bool validateHeader)
00097 {
00098 std::string suffix;
00099 ImageFileType *type = 0;
00100 std::map<std::string, ImageFileType *>::iterator sI;
00101 const char separator = '.';
00102 int i, l;
00103
00104 if(mimeType && *mimeType)
00105 {
00106 std::string mt = mimeType;
00107 normalizeMimetype(mt);
00108 if (mt.find('/') == std::string::npos)
00109 mt.insert(0, "image/");
00110 TypeMap::iterator tIt = _the->_typeMap.find(mt);
00111 if (tIt != _the->_typeMap.end())
00112 type = tIt->second;
00113 if (!type) {
00114 FWARNING (("Invalid mimeType %s in getFileType()\n", mimeType));
00115 }
00116 }
00117
00118 if(!type && fileName && *fileName)
00119 {
00120
00121 if(!type)
00122 {
00123 l = strlen(fileName);
00124 for(i = l - 1; i >= 0; i--)
00125 {
00126 if(fileName[i] == separator)
00127 break;
00128 }
00129
00130 if(i >= 0)
00131 {
00132 suffix.assign(&(fileName[i + 1]));
00133 normalizeSuffix(suffix);
00134 sI = _suffixTypeMap.find(suffix);
00135 type = (sI == _suffixTypeMap.end()) ? 0 : sI->second;
00136 }
00137 }
00138 }
00139
00140 if(validateHeader)
00141 {
00142
00143 bool implemented = false;
00144 if(fileName && *fileName &&
00145 type != NULL && !type->validateHeader(fileName, implemented))
00146 {
00147 FWARNING (("Found wrong image header trying to autodetect image type!\n"));
00148 for(sI = _suffixTypeMap.begin(); sI != _suffixTypeMap.end(); ++sI)
00149 {
00150 type = sI->second;
00151 if(type != NULL && type->validateHeader(fileName, implemented))
00152 {
00153 if(implemented)
00154 {
00155 FWARNING (("Autodetected '%s' image type!\n", sI->first.c_str()));
00156 return type;
00157 }
00158 }
00159 }
00160 FWARNING (("Couldn't autodetect image type!\n"));
00161 return NULL;
00162 }
00163 }
00164
00165 return type;
00166 }
00167
00168
00172 ImageFileType *ImageFileHandler::getDefaultType(void)
00173 {
00174 std::string dSuffix("opensg");
00175
00176 std::map<std::string,
00177 ImageFileType *>::iterator sI = _suffixTypeMap.find(dSuffix);
00178
00179
00180 ImageFileType *type = (sI == _suffixTypeMap.end()) ? 0 : sI->second;
00181
00182 if(!type)
00183 {
00184 FFATAL(("Can not find any default (suffix:%s) image handler\n",
00185 dSuffix.c_str()));
00186 }
00187
00188 return type;
00189 }
00190
00191
00192
00196 Int32 ImageFileHandler::getSuffixList(std::list<const Char8 *> & suffixList,
00197 UInt32 flags)
00198 {
00199 Int32 count = 0;
00200 std::map<std::string, ImageFileType *>::iterator sI;
00201
00202 suffixList.clear();
00203
00204 for ( sI = _suffixTypeMap.begin(); sI != _suffixTypeMap.end(); ++sI)
00205 {
00206 ImageFileType *type = sI->second;
00207 if(type->getFlags() & flags)
00208 {
00209 suffixList.push_back(sI->first.c_str());
00210 count++;
00211 }
00212 }
00213
00214 return count;
00215 }
00216
00217
00221 std::string ImageFileHandler::determineMimetypeFromName(const std::string &fileName)
00222 {
00223
00224 std::string::size_type pos = fileName.rfind('.');
00225 if (pos == std::string::npos)
00226 return std::string();
00227 std::string suffix = fileName.substr(pos + 1);
00228 normalizeSuffix(suffix);
00229
00230
00231 std::map<std::string, ImageFileType *>::iterator it = _suffixTypeMap.find(suffix);
00232 return it != _suffixTypeMap.end() ? std::string(it->second->getMimeType()) : std::string();
00233 }
00234
00235
00239 std::string ImageFileHandler::determineMimetypeFromSuffix(const std::string &suffix)
00240 {
00241 std::string s = suffix;
00242 normalizeSuffix(s);
00243
00244
00245 std::map<std::string, ImageFileType *>::iterator it = _suffixTypeMap.find(s);
00246 return it != _suffixTypeMap.end() ? std::string(it->second->getMimeType()) : std::string();
00247 }
00248
00249
00253 std::string ImageFileHandler::determineMimetypeFromStream(std::istream &is)
00254 {
00255 std::string mimetype;
00256 TypeMap::iterator it;
00257 for (it = _typeMap.begin(); it != _typeMap.end(); ++it)
00258 {
00259 mimetype = it->second->determineMimetypeFromStream(is);
00260 if (mimetype.empty() == false)
00261 break;
00262 }
00263 return mimetype;
00264 }
00265
00266
00273 ImagePtr ImageFileHandler::read(const char *fileName, const char *mimeType)
00274 {
00275 if(_readFP != NULL)
00276 return _readFP(fileName, mimeType);
00277
00278 ImagePtr image = Image::create();
00279
00280 if(read(image, fileName, mimeType) == false)
00281 {
00282 subRefCP(image);
00283 image = NullFC;
00284 }
00285 return image;
00286 }
00287
00288
00296 bool ImageFileHandler::read(ImagePtr &image, const char *fileName,
00297 const char *mimeType)
00298 {
00299 bool retCode = false;
00300 std::string fullFilePath;
00301
00302 if( _pPathHandler != NULL )
00303 {
00304 fullFilePath = _pPathHandler->findFile(fileName);
00305 }
00306 else
00307 {
00308 fullFilePath = fileName;
00309 }
00310
00311 if(fullFilePath.empty())
00312 {
00313 SWARNING << "couldn't find image file " << fileName << std::endl;
00314 return false;
00315 }
00316
00317 ImageFileType *type = getFileType(mimeType, fullFilePath.c_str(), true);
00318
00319 if(type)
00320 {
00321 FDEBUG(("try to image read %s as %s\n",
00322 fullFilePath.c_str(),
00323 type->getMimeType()));
00324
00325 retCode = type->read(image, fullFilePath.c_str());
00326
00327 if(retCode)
00328 {
00329 FDEBUG(("image: %dx%d\n", image->getWidth(), image->getHeight()));
00330 image->setAttachmentField(_fileNameKey, fileName);
00331 image->setAttachmentField(_fullFilePathKey, fullFilePath);
00332
00333
00334 std::string abspath;
00335 if(fullFilePath[0] != '/' && fullFilePath[0] != '\\' && fullFilePath[1] != ':')
00336 {
00337 std::string base = SceneFileHandler::the().getPathHandler()->getBaseFile();
00338 if(base.size() < 2 ||
00339 (base[0] != '/' && base[0] != '\\' && base[1] != ':'))
00340 {
00341 const char *cdir = Directory::getCurrent();
00342 abspath = cdir;
00343 #ifdef WIN32
00344 abspath += '\\';
00345 #else
00346 abspath += '/';
00347 #endif
00348 delete [] cdir;
00349 }
00350
00351 abspath += base;
00352 abspath += fullFilePath;
00353 }
00354 else
00355 {
00356 abspath = fullFilePath;
00357 }
00358
00359 beginEditCP(image, Image::NameFieldMask);
00360 image->setName(abspath);
00361 endEditCP(image, Image::NameFieldMask);
00362 }
00363 else
00364 {
00365 SWARNING << "could not read " << fullFilePath << std::endl;
00366 }
00367 }
00368 else
00369 {
00370 SWARNING << "could not read " << fullFilePath
00371 << "; unknown image format" << std::endl;
00372 }
00373
00374 return retCode;
00375 }
00376
00377
00378 void ImageFileHandler::setReadCB(readcbfp fp)
00379 {
00380 _readFP = fp;
00381 }
00382
00383 ImageFileHandler::readcbfp ImageFileHandler::getReadCB(void)
00384 {
00385 return _readFP;
00386 }
00387
00388
00396 bool ImageFileHandler::write(const ImagePtr &image, const char *fileName,
00397 const char *mimeType)
00398 {
00399 bool retCode = false;
00400 ImageFileType *type;
00401 const std::string *fNAttachment;
00402
00403 if (!fileName && (fNAttachment = image->findAttachmentField(_fileNameKey)))
00404 fileName = fNAttachment->c_str();
00405
00406 if ((type = getFileType(mimeType, fileName)))
00407 {
00408 SINFO << "try to write " << fileName << " as "
00409 << type->getMimeType() << std::endl;
00410 retCode = type->write(image, fileName);
00411 }
00412 else
00413 {
00414 SWARNING << "can't write " << fileName
00415 << "; unknown image format" << std::endl;
00416 }
00417
00418 return retCode;
00419 }
00420
00421
00422
00423 ImagePtr ImageFileHandler::read(std::istream &is, const std::string &mimeType)
00424 {
00425 ImagePtr image = Image::create();
00426
00427 if (read(image, is, mimeType) == false)
00428 {
00429 subRefCP(image);
00430 image = NullFC;
00431 }
00432
00433 return image;
00434 }
00435
00436
00437
00438 bool ImageFileHandler::read(ImagePtr &image, std::istream &is,
00439 const std::string &mimeType)
00440 {
00441 ImageFileType *type = getFileType(mimeType.c_str());
00442 return type == 0 ? false : type->read(image, is, mimeType);
00443 }
00444
00445
00446
00447 bool ImageFileHandler::write(const ImagePtr &image, std::ostream &os,
00448 const std::string &mimeType)
00449 {
00450 ImageFileType *type = getFileType(mimeType.c_str());
00451 return type == 0 ? false : type->write(image, os, mimeType);
00452 }
00453
00454
00458 PathHandler* ImageFileHandler::getPathHandler(void)
00459 {
00460 return _pPathHandler;
00461 }
00462
00463
00467 void ImageFileHandler::setPathHandler(PathHandler *pPathHandler)
00468 {
00469 _pPathHandler = pPathHandler;
00470 }
00471
00472
00480 UInt64 ImageFileHandler::restore(ImagePtr &image, const UChar8 *buffer,
00481 Int32 memSize)
00482 {
00483 return ImageFileType::restore(image, buffer, memSize);
00484 }
00485
00486
00494 UInt64 ImageFileHandler::store(const ImagePtr &image, const char *mimeType,
00495 UChar8 *buffer, Int32 memSize)
00496 {
00497 ImageFileType *type;
00498
00499 type = mimeType ? getFileType(mimeType) : getDefaultType();
00500
00501 return type->store(image, buffer, memSize);
00502 }
00503
00504
00514 UChar8 *ImageFileHandler::store(const ImagePtr &image, UInt64 &memSize,
00515 const char *mimeType)
00516 {
00517 ImageFileType *type = 0;
00518 UChar8 *mem = 0;
00519
00520 type = mimeType ? getFileType(mimeType) : getDefaultType();
00521 memSize = type->maxBufferSize(image);
00522
00523 if(memSize)
00524 {
00525 mem = new UChar8[size_t(memSize)];
00526 memSize = type->store(image, mem, Int32(memSize));
00527 }
00528 else
00529 {
00530 FFATAL(("Can not store the image as %s\n", type->getMimeType()));
00531 }
00532
00533 return mem;
00534 }
00535
00536
00540 void ImageFileHandler::dump(void)
00541 {
00542 std::map<std::string, ImageFileType *>::iterator sI;
00543
00544 for(sI = _suffixTypeMap.begin(); sI != _suffixTypeMap.end(); sI++)
00545 {
00546 FLOG (( "Image suffix: %s, mimeType: %s\n",
00547 sI->first.c_str(), sI->second->getMimeType() ));
00548 }
00549 }
00550
00551
00555 bool ImageFileHandler::addImageFileType(ImageFileType &fileType)
00556 {
00557 bool retCode = false;
00558 std::list<IDString >::const_iterator sI;
00559 std::map<std::string, ImageFileType *>::iterator smI;
00560 std::string suffix;
00561
00562 if(!_the)
00563 _the = new ImageFileHandler;
00564
00565 for( sI = fileType.getSuffixList().begin();
00566 sI != fileType.getSuffixList().end();
00567 ++sI)
00568 {
00569 suffix.assign(sI->str());
00570 normalizeSuffix(suffix);
00571 smI = _the->_suffixTypeMap.find(suffix);
00572 if(smI != _the->_suffixTypeMap.end())
00573 {
00574 SWARNING << "Can't add an image file type with suffix "
00575 << suffix << " a second time" << std::endl;
00576 }
00577 else
00578 {
00579 _the->_suffixTypeMap[suffix] = &fileType;
00580 retCode = true;
00581 }
00582 }
00583
00584 std::string mimetype = fileType.getMimeType();
00585 normalizeMimetype(mimetype);
00586 TypeMap::iterator tIt = _the->_typeMap.find(mimetype);
00587 if (tIt != _the->_typeMap.end())
00588 {
00589 SWARNING << "Can't add an image file type with mimetype "
00590 << mimetype << " a second time" << std::endl;
00591 }
00592 else
00593 _the->_typeMap[mimetype] = &fileType;
00594
00595 return retCode;
00596 }
00597
00598
00603 void ImageFileHandler::normalizeMimetype(std::string &mimetype)
00604 {
00605
00606 std::string::size_type endpos = mimetype.find(';');
00607 if (endpos == 0)
00608 {
00609 mimetype.erase();
00610 return;
00611 }
00612 if (endpos != std::string::npos)
00613 --endpos;
00614
00615
00616 endpos = mimetype.find_last_not_of(" \t\r\n", endpos);
00617 if (endpos == std::string::npos)
00618 {
00619 mimetype.erase();
00620 return;
00621 }
00622 mimetype.erase(endpos + 1);
00623
00624
00625 std::string::size_type startpos = mimetype.find_first_not_of(" \t\r\n");
00626 if (startpos == std::string::npos)
00627 {
00628 mimetype.erase();
00629 return;
00630 }
00631 mimetype.erase(0, startpos);
00632
00633
00634 std::transform(mimetype.begin(), mimetype.end(), mimetype.begin(), ::tolower);
00635 }
00636
00637
00641 void ImageFileHandler::normalizeSuffix(std::string &suffix)
00642 {
00643
00644 std::string::size_type endpos = suffix.find_last_not_of(" \t\r\n");
00645 if (endpos == std::string::npos)
00646 {
00647 suffix.erase();
00648 return;
00649 }
00650 suffix.erase(endpos + 1);
00651
00652
00653 std::string::size_type startpos = suffix.find_first_not_of(" \t\r\n");
00654 if (startpos == std::string::npos)
00655 {
00656 suffix.erase();
00657 return;
00658 }
00659 suffix.erase(0, startpos);
00660
00661
00662 std::transform(suffix.begin(), suffix.end(), suffix.begin(), ::tolower);
00663 }
00664
00665 bool ImageFileHandler::setOptions(const Char8 *suffix, const Char8 *options)
00666 {
00667 if(suffix == NULL)
00668 return false;
00669
00670 ImageFileType *type = getFileType(suffix);
00671 if(type == NULL)
00672 return false;
00673
00674 type->setOptions(options);
00675
00676 return true;
00677 }
00678
00679 const Char8 *ImageFileHandler::getOptions(const Char8 *suffix)
00680 {
00681 if(suffix == NULL)
00682 return NULL;
00683
00684 ImageFileType *type = getFileType(suffix);
00685
00686 if(type == NULL)
00687 return NULL;
00688
00689 return type->getOptions();
00690 }
00691
00692
00696 ImageFileHandler::ImageFileHandler(void) :
00697 _suffixTypeMap(),
00698 _typeMap(),
00699 _pPathHandler(0),
00700 _readFP(0)
00701 {}
00702
00703
00707 ImageFileHandler::~ImageFileHandler(void) {}
00708
00709
00713 ImageFileHandler & ImageFileHandler::the(void)
00714 {
00715 if(_the == NULL)
00716 _the = new ImageFileHandler;
00717 return *_the;
00718 }
00719
00720