changed: gcc8 base update
[opensg.git] / Source / System / Image / OSGImageFileHandler.cpp
blobc088c12a48b37f4fc439e1acc0b4d0366faccffb
1 /*---------------------------------------------------------------------------*\
2 * OpenSG *
3 * *
4 * *
5 * Copyright (C) 2000-2002 by the OpenSG Forum *
6 * *
7 * www.opensg.org *
8 * *
9 * contact: dirk@opensg.org, gerrit.voss@vossg.org, jbehr@zgdv.de *
10 * *
11 \*---------------------------------------------------------------------------*/
12 /*---------------------------------------------------------------------------*\
13 * License *
14 * *
15 * This library is free software; you can redistribute it and/or modify it *
16 * under the terms of the GNU Library General Public License as published *
17 * by the Free Software Foundation, version 2. *
18 * *
19 * This library is distributed in the hope that it will be useful, but *
20 * WITHOUT ANY WARRANTY; without even the implied warranty of *
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
22 * Library General Public License for more details. *
23 * *
24 * You should have received a copy of the GNU Library General Public *
25 * License along with this library; if not, write to the Free Software *
26 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
27 * *
28 \*---------------------------------------------------------------------------*/
29 /*---------------------------------------------------------------------------*\
30 * Changes *
31 * *
32 * *
33 * *
34 * *
35 * *
36 * *
37 \*---------------------------------------------------------------------------*/
39 #define OSG_COMPILE_IMAGEFILEHANDLER
41 #include <cstdlib>
42 #include <cstdio>
44 #include "OSGConfig.h"
46 #include "OSGLog.h"
47 #include "OSGBaseTypes.h"
48 #include "OSGPathHandler.h"
49 #include "OSGBaseFunctions.h"
50 #include "OSGFileSystem.h"
52 #include "OSGImageFileHandler.h"
53 #include "OSGBoostPathAttachment.h"
55 #include "OSGSingletonHolder.ins"
57 OSG_BEGIN_NAMESPACE
59 /*! \class ImageFileHandlerBase
61 Singelton Object/Class which holds all known ImageFileTypes.
62 The class is used to write/read Image objects to/from
63 files and to store/restore image data to/from memory blocks.
64 Utilizes the local pathHandler for file path handler and
65 construction. The PathHandler can be set from the application.
67 See \ref PageSystemImage for details.
71 /*****************************
72 * Types
73 *****************************/
75 OSG_SINGLETON_INST(ImageFileHandlerBase, addPostFactoryExitFunction)
77 template class SingletonHolder<ImageFileHandlerBase>;
79 /*****************************
80 * Classvariables
81 *****************************/
83 const std::string ImageFileHandlerBase::_fileNameKey ("fileName" );
84 const std::string ImageFileHandlerBase::_fullFilePathKey("fullFilePath");
86 /********************************
87 * Class methodes
88 *******************************/
90 /*******************************
91 *public
92 *******************************/
94 //-------------------------------------------------------------------------
95 /*! Method to find a ImageFileHandler for the given mimeType for
96 fileName suffix. Returns the ImageFileHandler object or Null.
99 ImageFileType *ImageFileHandlerBase::getFileType(const Char8 *mimeType,
100 const Char8 *fileName,
101 bool validateHeader)
103 std::string suffix;
104 ImageFileType *type = 0;
105 std::map<std::string,
106 ImageFileType *>::iterator sI;
107 const char separator = '.';
108 PtrDiffT i, l;
110 if(mimeType && *mimeType)
112 std::string mt = mimeType;
114 normalizeMimetype(mt);
116 if(mt.find('/') == std::string::npos)
117 mt.insert(0, "image/");
119 TypeMap::iterator tIt = _mimeTypeMap.find(mt);
121 if(tIt != _mimeTypeMap.end())
122 type = tIt->second;
124 if(!type)
126 FWARNING (("Invalid mimeType %s in getFileType()\n", mimeType));
130 if(!type && fileName && *fileName)
132 // check file suffix
134 if(!type)
136 l = strlen(fileName);
138 for(i = l - 1; i >= 0; i--)
140 if(fileName[i] == separator)
141 break;
144 if(i >= 0)
146 suffix.assign(&(fileName[i + 1]));
148 normalizeSuffix(suffix);
150 sI = _suffixTypeMap.find(suffix);
152 type = (sI == _suffixTypeMap.end()) ? 0 : sI->second;
157 if(validateHeader)
159 // now validate the header of the file
161 bool implemented = false;
163 if( fileName &&
164 *fileName &&
165 type != NULL &&
166 !type->validateHeader(fileName, implemented))
168 FWARNING (("Found wrong image header trying to "
169 "autodetect image type!\n"));
171 for(sI = _suffixTypeMap.begin(); sI != _suffixTypeMap.end(); ++sI)
173 type = sI->second;
175 if(type != NULL && type->validateHeader(fileName, implemented))
177 if(implemented)
179 FWARNING (("Autodetected '%s' image type!\n",
180 sI->first.c_str()));
182 return type;
187 FWARNING (("Couldn't autodetect image type!\n"));
189 return NULL;
193 return type;
196 //-------------------------------------------------------------------------
197 /*! Returns the default OpenSG ImageFileType
200 ImageFileType *ImageFileHandlerBase::getDefaultType(void)
202 std::string dSuffix("opensg");
204 std::map<std::string,
205 ImageFileType *>::iterator sI = _suffixTypeMap.find(dSuffix);
208 ImageFileType *type = (sI == _suffixTypeMap.end()) ? 0 : sI->second;
210 if(!type)
212 FFATAL(("Can not find any default (suffix:%s) image handler\n",
213 dSuffix.c_str()));
216 return type;
220 //-------------------------------------------------------------------------
221 /*! Returns the list of supported image suffixes
224 Int32 ImageFileHandlerBase::getSuffixList(std::list<const Char8 *> &suffixList,
225 UInt32 flags )
227 Int32 count = 0;
228 std::map<std::string,
229 ImageFileType *>::iterator sI;
231 suffixList.clear();
233 for(sI = _suffixTypeMap.begin(); sI != _suffixTypeMap.end(); ++sI)
235 ImageFileType *type = sI->second;
237 if(type->getFlags() & flags)
239 suffixList.push_back(sI->first.c_str());
240 count++;
244 return count;
247 const ImageFileHandlerBase::TypeMap& ImageFileHandlerBase::getSuffixTypeMap() const
249 return _suffixTypeMap;
252 const ImageFileHandlerBase::TypeMap& ImageFileHandlerBase::getMimeTypeMap() const
254 return _mimeTypeMap;
257 //-------------------------------------------------------------------------
259 Tries to determine the mime type from the file name.
262 std::string ImageFileHandlerBase::determineMimetypeFromName(
263 const std::string &fileName)
265 // Determine the suffix of the filename
266 std::string::size_type pos = fileName.rfind('.');
268 if(pos == std::string::npos)
269 return std::string();
271 std::string suffix = fileName.substr(pos + 1);
273 normalizeSuffix(suffix);
275 // Try to find the suffix in the map of extensions
276 std::map<std::string,
277 ImageFileType *>::iterator it = _suffixTypeMap.find(suffix);
279 return it != _suffixTypeMap.end() ?
280 std::string(it->second->getMimeType()) : std::string();
283 //-------------------------------------------------------------------------
285 tries to determine the mimetype of a stream.
288 std::string ImageFileHandlerBase::determineMimetypeFromStream(std::istream &is)
290 std::string mimetype;
291 TypeMap::iterator it;
293 for(it = _mimeTypeMap.begin(); it != _mimeTypeMap.end(); ++it)
295 mimetype = it->second->determineMimetypeFromStream(is);
297 if(mimetype.empty() == false)
298 break;
301 return mimetype;
304 //-------------------------------------------------------------------------
306 Tries to determine the mime type from the suffix.
308 std::string ImageFileHandlerBase::determineMimetypeFromSuffix(
309 const std::string &suffix)
311 std::string s = suffix;
313 normalizeSuffix(s);
315 // Try to find the suffix in the map of extensions
316 std::map<std::string, ImageFileType *>::iterator it =
317 _suffixTypeMap.find(s);
319 return it != _suffixTypeMap.end() ?
320 std::string(it->second->getMimeType()) : std::string();
323 //-------------------------------------------------------------------------
324 /*! Creates a new image and tries to read the raster data from
325 the given fileName. If the mimeType is not Null the method
326 will try to find the according ImageFileType. Otherwise it
327 will try to use the fileName suffix to determine the mimeType
331 ImageTransitPtr ImageFileHandlerBase::read(const Char8 *fileName,
332 const Char8 *mimeType)
334 if(_pReadCallback != NULL)
335 return _pReadCallback(fileName, mimeType);
337 ImageUnrecPtr image = Image::create();
339 if(read(image, fileName, mimeType) == false)
341 image = NULL;
344 return ImageTransitPtr(image);
347 //-------------------------------------------------------------------------
348 /*! Tries to read the raster data from
349 the given fileName into the given Image.
350 If the mimeType is not Null the method
351 will try to find the according ImageFileType. Otherwise it
352 will try to use the fileName suffix to determine the mimeType
355 bool ImageFileHandlerBase::read( Image *pImage,
356 const Char8 *fileName,
357 const Char8 *mimeType)
359 bool retCode = false;
360 std::string fullFilePath;
362 if(_pPathHandler != NULL)
364 fullFilePath = _pPathHandler->findFile(fileName);
366 else
368 fullFilePath = fileName;
371 if(fullFilePath.empty())
373 SWARNING << "couldn't find image file " << fileName << std::endl;
374 return false;
377 ImageFileType *type = getFileType(mimeType, fullFilePath.c_str(), true);
379 if(type != NULL)
381 FDEBUG(("try to image read %s as %s\n",
382 fullFilePath.c_str(),
383 type->getMimeType()));
385 retCode = type->read(pImage, fullFilePath.c_str());
387 if(retCode)
389 FDEBUG(("image: %dx%d\n",
390 pImage->getWidth(),
391 pImage->getHeight()));
393 pImage->setAttachmentField(_fileNameKey, fileName);
394 pImage->setAttachmentField(_fullFilePathKey, fullFilePath);
396 setBoostPath(pImage, BoostPath(fullFilePath));
398 // converting the path to a absolute path.
399 std::string abspath;
401 if(fullFilePath[0] != '/' &&
402 fullFilePath[0] != '\\' &&
403 fullFilePath[1] != ':')
405 std::string base;
407 if(getPathHandler() != NULL)
408 base = getPathHandler()->getBaseFile();
410 if(base.size() < 2 ||
411 (base[0] != '/' && base[0] != '\\' && base[1] != ':'))
413 const Char8 *cdir = Directory::getCurrent();
415 abspath = cdir;
416 #ifdef WIN32
417 abspath += '\\';
418 #else
419 abspath += '/';
420 #endif
421 delete [] cdir;
424 abspath += base;
425 abspath += fullFilePath;
427 else
429 abspath = fullFilePath;
432 pImage->setName(abspath);
434 else
436 SWARNING << "could not read " << fullFilePath << std::endl;
439 else
441 SWARNING << "could not read " << fullFilePath
442 << "; unknown image format" << std::endl;
445 return retCode;
448 void ImageFileHandlerBase::setReadCB(ReadCB pCB)
450 _pReadCallback = pCB;
453 ImageFileHandlerBase::ReadCB ImageFileHandlerBase::getReadCB(void)
455 return _pReadCallback;
458 //-------------------------------------------------------------------------
459 /*! Tries to write the raster data (from the given Image) to
460 the given fileName.
461 If the mimeType is not Null the method
462 will try to find the according ImageFileType. Otherwise it
463 will try to use the fileName suffix to determine the mimeType
466 bool ImageFileHandlerBase::write(Image const *pImage,
467 Char8 const *fileName,
468 Char8 const *mimeType)
470 bool retCode = false;
471 ImageFileType *type;
472 const std::string *fNAttachment;
474 if(!fileName && (fNAttachment = pImage->findAttachmentField(_fileNameKey)))
476 fileName = fNAttachment->c_str();
479 if((type = getFileType(mimeType, fileName)))
481 SINFO << "try to write "
482 << fileName
483 << " as "
484 << type->getMimeType()
485 << std::endl;
487 retCode = type->write(pImage, fileName);
489 else
491 SWARNING << "can't write "
492 << fileName
493 << "; unknown image format" << std::endl;
496 return retCode;
499 //-------------------------------------------------------------------------
501 ImageTransitPtr ImageFileHandlerBase::read( std::istream &is,
502 const std::string &mimeType)
504 ImageUnrecPtr image = Image::create();
506 if (read(image, is, mimeType) == false)
508 image = NULL;
511 return ImageTransitPtr(image);
514 //-------------------------------------------------------------------------
516 bool ImageFileHandlerBase::read( Image *pImage,
517 std::istream &is,
518 const std::string &mimeType)
520 ImageFileType *type = getFileType(mimeType.c_str());
522 return type == 0 ? false : type->read(pImage, is, mimeType);
525 //-------------------------------------------------------------------------
527 bool ImageFileHandlerBase::write(Image const *pImage,
528 std::ostream &os,
529 std::string const &mimeType)
531 ImageFileType *type = getFileType(mimeType.c_str());
533 return type == 0 ? false : type->write(pImage, os, mimeType);
537 ImageFileHandlerBase::ImageBlockAccessorPtr
538 ImageFileHandlerBase::open(const Char8 *fileName,
539 const Char8 *mimeType)
541 ImageBlockAccessorPtr returnValue;
542 std::string fullFilePath;
544 if(_pPathHandler != NULL)
546 fullFilePath = _pPathHandler->findFile(fileName);
548 else
550 fullFilePath = fileName;
553 if(fullFilePath.empty())
555 SWARNING << "couldn't find image file " << fileName << std::endl;
556 return returnValue;
559 ImageFileType *type = getFileType(mimeType, fullFilePath.c_str(), true);
561 if(type != NULL)
563 FDEBUG(("try to image read %s as %s\n",
564 fullFilePath.c_str(),
565 type->getMimeType()));
567 returnValue = type->open(fullFilePath.c_str());
569 else
571 SWARNING << "could not read " << fullFilePath
572 << "; unknown image format" << std::endl;
575 return returnValue;
579 //-------------------------------------------------------------------------
580 /*! Returns the path handler used
583 PathHandler* ImageFileHandlerBase::getPathHandler(void)
585 return _pPathHandler;
588 //-------------------------------------------------------------------------
589 /*! Method to set the path handler.
592 void ImageFileHandlerBase::setPathHandler(PathHandler *pPathHandler)
594 _pPathHandler = pPathHandler;
597 /*! Sets the option \a name to \a value for the ImageFileType that handles
598 files with the given \a suffix.
599 Returns \c true if the option was set successfully, \c false otherwise.
601 \param[in] suffix File extension to choose the image type
602 this option applies to.
603 \param[in] name Name of the option.
604 \param[in] value Value of the option.
605 \return Whether the value was set successfully.
607 bool
608 ImageFileHandlerBase::setOption(
609 const std::string &suffix,
610 const std::string &name,
611 const std::string &value )
613 bool retVal = false;
614 ImageFileType *type = getFileType(suffix.c_str());
616 if(type != NULL)
618 type->setOption(name, value);
619 retVal = true;
622 return retVal;
625 /*! Removes the option \a name from the ImageFileType that handles files
626 with the given \a suffix. If the option is not present \c false is
627 returned, \c true otherwise.
629 \param[in] suffix File extension to choose the image file type
630 this option applies to.
631 \param[in] name Name of the option.
632 \return Whether the option was successfully removed.
634 bool
635 ImageFileHandlerBase::unsetOption(
636 const std::string &suffix,
637 const std::string &name )
639 bool retVal = false;
640 ImageFileType *type = getFileType(suffix.c_str());
642 if(type != NULL)
644 retVal = type->unsetOption(name);
647 return retVal;
650 /*! Retrieves the option \a name from the ImageFileType that handles files
651 with the given \a suffix and stores its value in \a value.
652 Returns \c true if successful, \c false otherwise in which case \a value has
653 an undefined value.
655 \param[in] suffix File extension to choose the image type
656 this option applies to.
657 \param[in] name Name of the option.
658 \param[out] value Value the option.
659 \return Whether the option is present for the given ImageFileType.
661 bool
662 ImageFileHandlerBase::getOption(
663 const std::string &suffix,
664 const std::string &name,
665 std::string &value )
667 bool retVal = false;
668 ImageFileType *type = getFileType(suffix.c_str());
670 if(type != NULL)
672 retVal = type->getOption(name, value);
675 return retVal;
678 //-------------------------------------------------------------------------
679 /*! Tries to restore the raster data from
680 the given memblock into the given Image.
681 If the mimeType is not Null the method
682 will try to find the according ImageFileType. Otherwise it
683 will try to use the fileName suffix to determine the mimeType
686 UInt64 ImageFileHandlerBase::restore( Image *pImage,
687 const UChar8 *buffer,
688 Int32 memSize)
690 return ImageFileType::restore(pImage, buffer, memSize);
693 //-------------------------------------------------------------------------
694 /*! Tries to store the raster data (from the given Image) to
695 the given memBlock.
696 If the mimeType is not Null the method
697 will try to find the according ImageFileType. Otherwise it
698 will try to use the fileName suffix to determine the mimeType
701 UInt64 ImageFileHandlerBase::store(Image const *pImage,
702 Char8 const *mimeType,
703 UChar8 *buffer,
704 Int32 memSize )
706 ImageFileType *type;
708 type = mimeType ? getFileType(mimeType) : getDefaultType();
710 return type->store(pImage, buffer, memSize);
713 //-------------------------------------------------------------------------
714 /*! Tries to store the raster data (from the given Image) to
715 a new memBlock. The method will automatically allocate and return a
716 sufficient amount of memory with new. The application has
717 to free the memory with 'delete [] mem'
718 If the mimeType is not Null the method
719 will try to find the according ImageFileType. Otherwise it
720 will try to use the fileName suffix to determine the mimeType
723 UChar8 *ImageFileHandlerBase::store(Image const *pImage,
724 UInt64 &memSize,
725 Char8 const *mimeType)
727 ImageFileType *type = 0;
728 UChar8 *mem = 0;
730 type = mimeType ? getFileType(mimeType) : getDefaultType();
731 memSize = type->maxBufferSize(pImage);
733 if(memSize)
735 mem = new UChar8[size_t(memSize)];
737 memSize = type->store(pImage, mem, Int32(memSize));
739 else
741 FFATAL(("Can not store the image as %s\n", type->getMimeType()));
744 return mem;
747 //-------------------------------------------------------------------------
748 /*! The dump method just writes some object debugging info to the LOG stream
751 void ImageFileHandlerBase::dump(void)
753 std::map<std::string, ImageFileType *>::iterator sI;
755 for(sI = _suffixTypeMap.begin(); sI != _suffixTypeMap.end(); sI++)
757 FLOG (( "Image suffix: %s, mimeType: %s\n",
758 sI->first.c_str(), sI->second->getMimeType() ));
762 //-------------------------------------------------------------------------
763 /*! Internal Method to add a new ImageFileType
766 bool ImageFileHandlerBase::addImageFileType(ImageFileType &fileType)
768 bool retCode = false;
769 std::list<std::string >::const_iterator sI;
770 std::map <std::string,
771 ImageFileType *>::iterator smI;
772 std::string suffix;
774 for( sI = fileType.getSuffixList().begin();
775 sI != fileType.getSuffixList().end();
776 ++sI)
778 suffix.assign(sI->c_str());
780 normalizeSuffix(suffix);
782 smI = _suffixTypeMap.find(suffix);
784 if(smI != _suffixTypeMap.end())
786 SWARNING << "Can't add an image file type with suffix "
787 << suffix << " a second time" << std::endl;
789 else
791 _suffixTypeMap[suffix] = &fileType;
793 retCode = true;
797 std::string mimetype = fileType.getMimeType();
799 normalizeMimetype(mimetype);
801 TypeMap::iterator tIt = _mimeTypeMap.find(mimetype);
803 if(tIt != _mimeTypeMap.end())
805 SWARNING << "Can't add an image file type with mimetype "
806 << mimetype << " a second time" << std::endl;
808 else
810 _mimeTypeMap[mimetype] = &fileType;
813 return retCode;
816 //----------------------------------------------------------------------
818 Normalizes a mime type, i.e. removes parameters and whitespaces
819 and transforms it to lowercase
822 void ImageFileHandlerBase::normalizeMimetype(std::string &mimetype)
824 // Remove any parameters
825 std::string::size_type endpos = mimetype.find(';');
827 if (endpos == 0)
829 mimetype.erase();
830 return;
833 if (endpos != std::string::npos)
834 --endpos;
836 // Remove trailing whitespace
838 endpos = mimetype.find_last_not_of(" \t\r\n", endpos);
840 if (endpos == std::string::npos)
842 mimetype.erase();
843 return;
846 mimetype.erase(endpos + 1);
848 // Remove leading whitespace
849 std::string::size_type startpos = mimetype.find_first_not_of(" \t\r\n");
851 if(startpos == std::string::npos)
853 mimetype.erase();
854 return;
857 mimetype.erase(0, startpos);
859 // Transform to lower case
860 std::transform(mimetype.begin(),
861 mimetype.end (),
862 mimetype.begin(),
863 ::tolower);
866 //-------------------------------------------------------------------------
868 Normalizes a suffix, i.e. removes whitespaces and transforms it to lowercase
870 void ImageFileHandlerBase::normalizeSuffix(std::string &suffix)
872 // Remove trailing whitespace
873 std::string::size_type endpos = suffix.find_last_not_of(" \t\r\n");
875 if (endpos == std::string::npos)
877 suffix.erase();
878 return;
881 suffix.erase(endpos + 1);
883 // Remove leading whitespace
884 std::string::size_type startpos = suffix.find_first_not_of(" \t\r\n");
886 if (startpos == std::string::npos)
888 suffix.erase();
889 return;
892 suffix.erase(0, startpos);
894 // Transform to lower case
895 std::transform(suffix.begin(), suffix.end(), suffix.begin(), ::tolower);
898 //-------------------------------------------------------------------------
899 /*! Default Constructor
902 ImageFileHandlerBase::ImageFileHandlerBase(void) :
903 _pReadCallback(NULL),
904 _pPathHandler (NULL),
905 _suffixTypeMap( ),
906 _mimeTypeMap ( )
910 //-------------------------------------------------------------------------
911 /*! Destructor
914 ImageFileHandlerBase::~ImageFileHandlerBase(void)
919 OSG_END_NAMESPACE