fixed: auto_ptr -> unique_ptr
[opensg.git] / Source / System / Image / OSGImageFileType.cpp
blob6d98a861a6fcfbb008a1f97be5d7af3c15b51db6
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 // System declarations
40 #include "OSGConfig.h"
41 #include <iostream>
43 // Application declarations
44 // to get ntons/ntohs
46 // Class declarations
47 #include "OSGImageFileType.h"
48 #include "OSGImageFileHandler.h"
49 #include "OSGImageGenericAtt.h"
50 #include "OSGLog.h"
52 OSG_BEGIN_NAMESPACE
54 ImageBlockAccessor::~ImageBlockAccessor(void)
56 _pGeoRef = NULL;
59 ImageBlockAccessor::ImageBlockAccessor(void) :
60 _pGeoRef (NULL ),
61 _vSize (0, 0 ),
62 _eImgType (Image::OSG_INVALID_IMAGEDATATYPE),
63 _eImgFormat (Image::OSG_INVALID_PF ),
64 _fNoDataValue(0 )
68 Vec2i ImageBlockAccessor::getSize(void)
70 return _vSize;
73 Image::Type ImageBlockAccessor::getType(void)
75 return _eImgType;
78 Image::PixelFormat ImageBlockAccessor::getFormat(void)
80 return _eImgFormat;
83 GeoReferenceAttachment *ImageBlockAccessor::getGeoRef(void)
85 return _pGeoRef;
88 Real64 ImageBlockAccessor::getNoDataValue(void)
90 return _fNoDataValue;
95 BlockAccessWrapper::~BlockAccessWrapper(void)
97 _pImage = NULL;
101 bool BlockAccessWrapper::isOpen(void)
103 return (_pImage != NULL);
106 bool BlockAccessWrapper::readBlockA16(Vec2i vSampleOrigin,
107 Int32 iTextureSize,
108 UInt16 *pTarget,
109 Int32 iTargetSizeBytes)
111 if(_pImage == NULL)
112 return false;
114 const UInt8 *pData = _pImage->getData();
116 UInt8 *pDst = reinterpret_cast<UInt8 *>(pTarget);
118 UInt32 destIdx = 0;
120 Int32 xMin = vSampleOrigin.x();
121 Int32 xMax = vSampleOrigin.x() + iTextureSize;
123 Int32 yMin = vSampleOrigin.y();
124 Int32 yMax = vSampleOrigin.y() + iTextureSize;
126 for(Int32 y = yMin; y < yMax; y++)
128 for(Int32 x = xMin; x < xMax; x++)
130 for(Int32 i = 0; i < 2; i++)
132 if(y >= _pImage->getHeight() ||
133 x >= _pImage->getWidth() )
135 pDst[destIdx] = 0;
137 else
139 pDst[destIdx] =
140 pData[((y) * _pImage->getWidth() + x) * 2 + i];
143 destIdx++;
147 destIdx += (iTextureSize - (xMax - xMin)) * 2;
150 return true;
153 bool BlockAccessWrapper::readBlockA16(Vec2i vSampleOrigin,
154 Int32 iTextureSize,
155 Int16 *pTarget,
156 Int32 iTargetSizeBytes)
158 if(_pImage == NULL)
159 return false;
161 #if 0
162 const UInt8 *pData = _pImage->getData();
164 UInt8 *pDst = (UInt8 *) pTarget;
166 UInt32 destIdx = 0;
168 Int32 xMin = vSampleOrigin.x();
169 Int32 xMax = vSampleOrigin.x() + iTextureSize;
171 Int32 yMin = vSampleOrigin.y();
172 Int32 yMax = vSampleOrigin.y() + iTextureSize;
174 for(UInt32 y = yMin; y < yMax; y++)
176 for(UInt32 x = xMin; x < xMax; x++)
178 for(UInt32 i = 0; i < 2; i++)
180 if(y >= _pImage->getHeight() ||
181 x >= _pImage->getWidth() )
183 pDst[destIdx] = 0;
185 else
187 pDst[destIdx] =
188 pData[((y) * _pImage->getWidth() + x) * 2 + i];
191 destIdx++;
195 destIdx += (iTextureSize - (xMax - xMin)) * 2;
197 #else
198 const Int16 *pData = reinterpret_cast<const Int16 *>(_pImage->getData());
200 UInt32 destIdx = 0;
202 Int32 xMin = vSampleOrigin.x();
203 Int32 xMax = vSampleOrigin.x() + iTextureSize;
205 Int32 yMin = vSampleOrigin.y();
206 Int32 yMax = vSampleOrigin.y() + iTextureSize;
208 for(Int32 y = yMin; y < yMax; y++)
210 for(Int32 x = xMin; x < xMax; x++)
212 if(y >= _pImage->getHeight() ||
213 x >= _pImage->getWidth() )
215 pTarget[destIdx] = 0;
217 else
219 pTarget[destIdx] =
220 pData[((y) * _pImage->getWidth() + x)];
223 ++destIdx;
226 #endif
228 return true;
231 BlockAccessWrapper::BlockAccessWrapper(void) :
232 Inherited( ),
233 _pImage (NULL)
237 void BlockAccessWrapper::open(const Char8 *szFilename)
239 _pImage = ImageFileHandler::the()->read(szFilename);
241 if(_pImage != NULL)
243 _pGeoRef =
244 dynamic_cast<GeoReferenceAttachment *>(
245 _pImage->findAttachment(
246 GeoReferenceAttachment::getClassType().getGroupId()));
248 _vSize.setValues(_pImage->getWidth(),
249 _pImage->getHeight());
251 _eImgType = Image::Type (_pImage->getDataType ());
252 _eImgFormat = Image::PixelFormat(_pImage->getPixelFormat());
254 fprintf(stderr, "FOOO\n");
256 _pImage->dump();
261 /*! \class ImageFileType
264 //-------------------------------------------------------------------------
266 Helper method to convert the Head block from net to host format
269 bool ImageFileType::Head::netToHost(void)
271 pixelFormat = osgNetToHost<UInt16>(pixelFormat);
272 width = osgNetToHost<UInt16>(width);
273 height = osgNetToHost<UInt16>(height);
274 depth = osgNetToHost<UInt16>(depth);
275 mipmapCount = osgNetToHost<UInt16>(mipmapCount);
276 frameCount = osgNetToHost<UInt16>(frameCount);
277 frameDelay = osgNetToHost<UInt16>(frameDelay);
278 sideCount = osgNetToHost<UInt16>(sideCount);
279 dataType = osgNetToHost<UInt16>(dataType);
280 _reserved3 = 0;
281 _reserved4 = 0;
282 attachmentSize = osgNetToHost<UInt16>(attachmentSize);
284 return true;
288 //-------------------------------------------------------------------------
290 Helper method to convert the Head block from host to net format
293 bool ImageFileType::Head::hostToNet(void)
295 pixelFormat = osgHostToNet<UInt16>(pixelFormat);
296 width = osgHostToNet<UInt16>(width);
297 height = osgHostToNet<UInt16>(height);
298 depth = osgHostToNet<UInt16>(depth);
299 mipmapCount = osgHostToNet<UInt16>(mipmapCount);
300 frameCount = osgHostToNet<UInt16>(frameCount);
301 frameDelay = osgHostToNet<UInt16>(frameDelay);
302 sideCount = osgHostToNet<UInt16>(sideCount);
303 dataType = osgHostToNet<UInt16>(dataType);
304 _reserved3 = 0;
305 _reserved4 = 0;
306 attachmentSize = osgHostToNet<UInt16>(attachmentSize);
308 return true;
311 //-------------------------------------------------------------------------
312 /*! Get method for the mime type
315 const Char8 *ImageFileType::getMimeType(void) const
317 return _mimeType.c_str();
320 //-------------------------------------------------------------------------
322 bool ImageFileType::read(Image *pImage, const Char8 *fileName)
324 std::ifstream is(fileName, std::ios::binary);
326 if (is.good() == false)
327 return false;
329 return read(pImage, is, std::string());
332 //-------------------------------------------------------------------------
334 bool ImageFileType::write(Image const * pImage, const Char8 *fileName)
336 std::ofstream os(fileName, std::ios::binary);
338 if (os.good() == false)
339 return false;
341 return write(pImage, os, std::string());
344 //-------------------------------------------------------------------------
345 /*! Get method for the suffix list container
348 const std::list<std::string> &ImageFileType::getSuffixList(void) const
350 return _suffixList;
353 //-------------------------------------------------------------------------
355 bool ImageFileType::validateHeader(const Char8 *fileName, bool &implemented)
357 implemented = false;
359 return true;
362 ImageBlockAccessorPtr ImageFileType::open(const Char8 *szFilename)
364 BlockAccessWrapperPtr returnValue(new BlockAccessWrapper);
366 returnValue->open(szFilename);
368 return returnValue;
371 //-------------------------------------------------------------------------
373 Tries to fill the image object with the data read from
374 the given input stream. Returns true on success.
377 bool ImageFileType::read( Image *pImage,
378 std::istream &is,
379 const std::string &mimetype)
381 SWARNING << getMimeType()
382 << " read from stream is not implemented"
383 << endLog;
384 return false;
387 //-------------------------------------------------------------------------
389 Tries to write the image object to the given output stream.
390 Returns true on success.
393 bool ImageFileType::write(Image const *pImage,
394 std::ostream &os,
395 std::string const &mimetype)
397 SWARNING << getMimeType()
398 << " write to stream is not implemented"
399 << endLog;
401 return false;
404 //-------------------------------------------------------------------------
406 Tries to determine the mime type of the data provided by an input stream
407 by searching for magic bytes. Returns the mime type or an empty string
408 when the function could not determine the mime type.
411 std::string ImageFileType::determineMimetypeFromStream(std::istream &is)
413 return std::string();
416 //-------------------------------------------------------------------------
417 /*! Constructor which takes a suffix array and size to add the
418 ImageFileType to the Singleton ImageFileHandler
421 ImageFileType::ImageFileType(const char *mimeType,
422 const Char8 *suffixArray[],
423 UInt16 suffixByteCount,
424 UInt32 flags ) :
426 Inherited (flags),
427 _suffixList( ),
428 _mimeType ( )
430 Int32 suffixCount = suffixByteCount / sizeof(const Char8 *);
431 Int32 i = 0;
432 std::list<std::string>::iterator sI;
434 if (!mimeType)
436 FFATAL (("ImageFileType without valid mimeType\n"));
439 _mimeType.assign(mimeType);
441 _suffixList.resize(suffixCount);
443 for(sI = _suffixList.begin(); sI != _suffixList.end(); sI++)
445 sI->assign(suffixArray[i++]);
446 SINFO << "add image suffix: " << *sI << endLog;
449 ImageFileHandler::the()->addImageFileType(*this);
452 //-------------------------------------------------------------------------
453 /*! Destructor
456 ImageFileType::~ImageFileType(void)
460 //-------------------------------------------------------------------------
461 /*! Abstract restore method. Should be overwriten by an concrete derived
462 class. Tries to restore the image data from the given memblock.
465 UInt64 ImageFileType::restoreData( Image * ,
466 const UChar8 *OSG_CHECK_ARG(buffer ),
467 Int32 OSG_CHECK_ARG(memSize)) const
469 FWARNING(("ImageXFileType::restoreData() not impl. for mimeType %s\n",
470 getMimeType()));
472 return 0;
475 //-------------------------------------------------------------------------
476 /*! Abstract restore method. Should be overwriten by an concrete derived
477 class. Tries to store the given image data to the given memblock
480 UInt64 ImageFileType::storeData(Image const * ,
481 UChar8 *OSG_CHECK_ARG(buffer ),
482 Int32 OSG_CHECK_ARG(memSize)) const
484 FWARNING(("ImageXFileType::storeData() not impl. for mimeType %s\n",
485 getMimeType()));
487 return 0;
490 //-------------------------------------------------------------------------
491 /*! Tries to restore the Imagedata from the given memblock. The buffer must
492 include a ImageFileType::Head data block.
495 UInt64 ImageFileType::restore( Image *pImage,
496 const UChar8 *buffer,
497 Int32 memSize)
499 long imageSize, headSize = sizeof(Head);
500 unsigned long size = 0, attachmentSize;
501 Head head;
502 const UChar8 *data = buffer ? (buffer + headSize) : 0;
503 ImageFileType *type;
504 std::string mimeType;
505 Image::Type dataType;
507 if((pImage != NULL) && (buffer != NULL) && (memSize >= headSize))
509 // Copy header. Otherwise netToHost would change the original
510 // data structur.
512 memcpy(&head,buffer,sizeof(Head));
513 head.netToHost();
514 mimeType =
515 ImageFileHandler::the()->determineMimetypeFromSuffix(head.suffix);
517 if((type = ImageFileHandler::the()->getFileType(mimeType.c_str(), 0)))
519 if (head.dataType)
520 dataType = Image::Type(head.dataType);
521 else
522 dataType = Image::OSG_UINT8_IMAGEDATA;
524 pImage->set(Image::PixelFormat(head.pixelFormat),
525 head.width,
526 head.height,
527 head.depth,
528 head.mipmapCount,
529 head.frameCount,
530 float(head.frameDelay) / 1000.0,
532 dataType,
533 true,
534 head.sideCount);
536 imageSize = static_cast<unsigned long>(
537 type->restoreData(pImage, data, memSize - headSize));
539 attachmentSize = 0; // head->attachmentSize;
542 if ((attachmentSize = head->attachmentSize))
544 attData = (char*)(buffer + headSize + imageSize);
545 attKey = attData;
546 attValue = 0;
547 for (i = 0; i < (attachmentSize-1); i++) {
548 if (attData[i] == 0)
549 if (attKey) {
550 attValue = &(attData[i+1]);
551 image->setAttachmentField (attKey,attValue);
552 attKey = attValue = 0;
554 else
555 attKey = &(attData[i+1]);
557 if (attKey || attValue) {
558 FFATAL (("Attachment restore error\n"));
563 size = headSize + imageSize + attachmentSize;
565 FDEBUG (( "Restore image data: %lu (%lu/%lu/%lu)\n",
566 size, headSize, imageSize, attachmentSize ));
569 else
571 imageSize = 0;
573 FWARNING(("Can not restore image data, invalid mimeType: %s\n",
574 mimeType.empty() == false ?
575 mimeType.c_str() : "Unknown"));
579 return size;
582 //-------------------------------------------------------------------------
583 /*! Tries to store the raster data to the given mem block.
584 Will include a ImageFileType::Head description and the data encoded
585 as 'mimeType'
588 UInt64 ImageFileType::store(Image const *pImage,
589 Char8 const *mimeType,
590 UChar8 *buffer,
591 Int32 memSize)
593 ImageFileType *type = ImageFileHandler::the()->getFileType(mimeType);
595 return type ? type->store(pImage, buffer, memSize) : 0;
598 //-------------------------------------------------------------------------
599 /*! Tries to store the raster data to the given mem block.
600 Will include a ImageFileType::Head description for the derived
601 concreate mimeType.
604 UInt64 ImageFileType::store(Image const *pImage,
605 UChar8 *buffer,
606 Int32 memSize)
608 Head *head;
609 unsigned long dataSize = 0, headSize = sizeof(Head);
610 unsigned long attachmentSize;
611 UChar8 *dest;
612 const UChar8 *src = pImage->getData();
613 std::map<std::string, std::string>::const_iterator aI;
614 std::string value;
616 attachmentSize = 0;
618 // get attachment size
620 ImageGenericAttPtr att=ImageGenericAttPtr::dcast(
621 const_cast<Image*>(image.getCPtr())->findAttachment(
622 ImageGenericAtt::getClassType().getGroupId()));
623 if(att != NULL)
625 for(i = 0; i < (att->getType().getNumFieldDescs()-1); ++i)
627 FieldDescription *fieldDesc=att->getType().getFieldDescription(i);
628 Field *field=att->getField(i);
629 if (fieldDesc && field)
631 field->getValueByStr(value);
632 attachmentSize += strlen( fieldDesc->getName().str() ) + 1;
633 attachmentSize += value.length() + 1;
635 std::cout << fieldDesc->getName().str() << std::endl;
636 std::cout << value << std::endl;
638 else
640 FFATAL (("Invalid Attachment in ImageFileType::store()\n"));
646 if (buffer)
648 head = reinterpret_cast<Head *>(buffer);
650 head->pixelFormat = pImage->getPixelFormat();
651 head->width = pImage->getWidth();
652 head->height = pImage->getHeight();
653 head->depth = pImage->getDepth();
654 head->mipmapCount = pImage->getMipMapCount();
655 head->frameCount = pImage->getFrameCount();
656 head->frameDelay = short(pImage->getFrameDelay() * 1000.0);
657 head->sideCount = pImage->getSideCount();
658 head->dataType = pImage->getDataType();
659 head->attachmentSize = static_cast<unsigned short>(attachmentSize);
660 head->hostToNet();
662 strcpy(head->suffix, _suffixList.front().c_str());
664 dest = static_cast<UChar8 *>(buffer + headSize);
666 if(src)
668 dataSize = static_cast<unsigned long>(
669 storeData(pImage, dest, memSize - headSize));
672 dest = static_cast<UChar8 *>(buffer + headSize + dataSize);
675 if(att != NULL)
677 for(i = 0; i < (att->getType().getNumFieldDescs()-1); ++i)
679 FieldDescription *fieldDesc=att->getType().getFieldDescription(i);
680 Field *field=att->getField(i);
681 if (field && fieldDesc)
683 field->getValueByStr(value);
685 l = strlen( fieldDesc->getName().str() );
686 for (i = 0; i < l; i++)
687 *dest++ = fieldDesc->getName().str()[i];
688 *dest++ = 0;
689 l = value.length();
690 for (i = 0; i < l; i++)
691 *dest++ = value[i];
692 *dest++ = 0;
694 else
696 FFATAL (("Invalid Attachment in ImageFileType::store()\n"));
702 FDEBUG (( "Store image data: %lu (%lu/%lu/%lu)\n",
703 headSize + dataSize + attachmentSize, headSize, dataSize,
704 attachmentSize ));
706 else
708 FFATAL (("Invalid buffer in ImageFileType::store()\n"));
711 return (headSize + dataSize + attachmentSize);
714 //-------------------------------------------------------------------------
715 /*! Returns the max buffer size needed to store the Image (Head + mimeType
716 specific data block)
719 UInt64 ImageFileType::maxBufferSize(Image const * pImage)
721 std::string value;
722 unsigned long size, attachmentSize;
723 unsigned long imageSize = pImage->getSize(), headSize = sizeof(Head);
725 std::map<std::string, std::string>::const_iterator aI;
727 attachmentSize = 0;
729 // get attachment size
731 ImageGenericAttPtr att=ImageGenericAttPtr::dcast(
732 const_cast<Image*>(image.getCPtr())->findAttachment(
733 ImageGenericAtt::getClassType().getGroupId()));
734 if(att != NULL)
736 for(i = 0; i < (att->getType().getNumFieldDescs()-1); ++i)
738 FieldDescription *fieldDesc=att->getType().getFieldDescription(i);
739 Field *field=att->getField(i);
740 if (field && fieldDesc)
742 field->getValueByStr(value);
743 attachmentSize += strlen( fieldDesc->getName().str() ) + 1;
744 attachmentSize += value.length() + 1;
746 else
748 FFATAL (("Invalid Attachment in ImageFileType::maxBufferSize()\n"));
754 size = headSize + imageSize + attachmentSize;
756 FINFO (( "ImageFileType::maxBufferSize(): %lu (%lu/%lu/%lu)\n",
757 size, headSize, imageSize, attachmentSize ));
759 return size;
762 //-------------------------------------------------------------------------
763 /*! The dump method just writes some object debugging info to the LOG stream
766 void ImageFileType::dump(void)
768 std::list<std::string>::iterator sI;
770 SLOG << getMimeType();
772 if(_suffixList.empty())
774 SLOG << ": Suffix: ";
776 for(sI = _suffixList.begin(); sI != _suffixList.end(); sI++)
778 Log().stream(OSG::LOG_DEBUG) << sI->c_str() << " ";
782 std::cerr << std::endl;
785 OSG_END_NAMESPACE