1 /*---------------------------------------------------------------------------*\
5 * Copyright (C) 2000-2002 by the OpenSG Forum *
9 * contact: dirk@opensg.org, gerrit.voss@vossg.org, jbehr@zgdv.de *
11 \*---------------------------------------------------------------------------*/
12 /*---------------------------------------------------------------------------*\
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. *
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. *
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. *
28 \*---------------------------------------------------------------------------*/
29 /*---------------------------------------------------------------------------*\
37 \*---------------------------------------------------------------------------*/
39 // System declarations
40 #include "OSGConfig.h"
43 // Application declarations
47 #include "OSGImageFileType.h"
48 #include "OSGImageFileHandler.h"
49 #include "OSGImageGenericAtt.h"
54 ImageBlockAccessor::~ImageBlockAccessor(void)
59 ImageBlockAccessor::ImageBlockAccessor(void) :
62 _eImgType (Image::OSG_INVALID_IMAGEDATATYPE
),
63 _eImgFormat (Image::OSG_INVALID_PF
),
68 Vec2i
ImageBlockAccessor::getSize(void)
73 Image::Type
ImageBlockAccessor::getType(void)
78 Image::PixelFormat
ImageBlockAccessor::getFormat(void)
83 GeoReferenceAttachment
*ImageBlockAccessor::getGeoRef(void)
88 Real64
ImageBlockAccessor::getNoDataValue(void)
95 BlockAccessWrapper::~BlockAccessWrapper(void)
101 bool BlockAccessWrapper::isOpen(void)
103 return (_pImage
!= NULL
);
106 bool BlockAccessWrapper::readBlockA16(Vec2i vSampleOrigin
,
109 Int32 iTargetSizeBytes
)
114 const UInt8
*pData
= _pImage
->getData();
116 UInt8
*pDst
= reinterpret_cast<UInt8
*>(pTarget
);
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() )
140 pData
[((y
) * _pImage
->getWidth() + x
) * 2 + i
];
147 destIdx
+= (iTextureSize
- (xMax
- xMin
)) * 2;
153 bool BlockAccessWrapper::readBlockA16(Vec2i vSampleOrigin
,
156 Int32 iTargetSizeBytes
)
162 const UInt8
*pData
= _pImage
->getData();
164 UInt8
*pDst
= (UInt8
*) pTarget
;
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() )
188 pData
[((y
) * _pImage
->getWidth() + x
) * 2 + i
];
195 destIdx
+= (iTextureSize
- (xMax
- xMin
)) * 2;
198 const Int16
*pData
= reinterpret_cast<const Int16
*>(_pImage
->getData());
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;
220 pData
[((y
) * _pImage
->getWidth() + x
)];
231 BlockAccessWrapper::BlockAccessWrapper(void) :
237 void BlockAccessWrapper::open(const Char8
*szFilename
)
239 _pImage
= ImageFileHandler::the()->read(szFilename
);
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");
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
);
282 attachmentSize
= osgNetToHost
<UInt16
>(attachmentSize
);
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
);
306 attachmentSize
= osgHostToNet
<UInt16
>(attachmentSize
);
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)
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)
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
353 //-------------------------------------------------------------------------
355 bool ImageFileType::validateHeader(const Char8
*fileName
, bool &implemented
)
362 ImageBlockAccessorPtr
ImageFileType::open(const Char8
*szFilename
)
364 BlockAccessWrapperPtr
returnValue(new BlockAccessWrapper
);
366 returnValue
->open(szFilename
);
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
,
379 const std::string
&mimetype
)
381 SWARNING
<< getMimeType()
382 << " read from stream is not implemented"
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
,
395 std::string
const &mimetype
)
397 SWARNING
<< getMimeType()
398 << " write to stream is not implemented"
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
,
430 Int32 suffixCount
= suffixByteCount
/ sizeof(const Char8
*);
432 std::list
<std::string
>::iterator sI
;
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 //-------------------------------------------------------------------------
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",
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",
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
,
499 long imageSize
, headSize
= sizeof(Head
);
500 unsigned long size
= 0, attachmentSize
;
502 const UChar8
*data
= buffer
? (buffer
+ headSize
) : 0;
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
512 memcpy(&head
,buffer
,sizeof(Head
));
515 ImageFileHandler::the()->determineMimetypeFromSuffix(head
.suffix
);
517 if((type
= ImageFileHandler::the()->getFileType(mimeType
.c_str(), 0)))
520 dataType
= Image::Type(head
.dataType
);
522 dataType
= Image::OSG_UINT8_IMAGEDATA
;
524 pImage
->set(Image::PixelFormat(head
.pixelFormat
),
530 float(head
.frameDelay
) / 1000.0,
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);
547 for (i = 0; i < (attachmentSize-1); i++) {
550 attValue = &(attData[i+1]);
551 image->setAttachmentField (attKey,attValue);
552 attKey = attValue = 0;
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
));
573 FWARNING(("Can not restore image data, invalid mimeType: %s\n",
574 mimeType
.empty() == false ?
575 mimeType
.c_str() : "Unknown"));
582 //-------------------------------------------------------------------------
583 /*! Tries to store the raster data to the given mem block.
584 Will include a ImageFileType::Head description and the data encoded
588 UInt64
ImageFileType::store(Image
const *pImage
,
589 Char8
const *mimeType
,
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
604 UInt64
ImageFileType::store(Image
const *pImage
,
609 unsigned long dataSize
= 0, headSize
= sizeof(Head
);
610 unsigned long attachmentSize
;
612 const UChar8
*src
= pImage
->getData();
613 std::map
<std::string
, std::string
>::const_iterator aI
;
618 // get attachment size
620 ImageGenericAttPtr att=ImageGenericAttPtr::dcast(
621 const_cast<Image*>(image.getCPtr())->findAttachment(
622 ImageGenericAtt::getClassType().getGroupId()));
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;
640 FFATAL (("Invalid Attachment in ImageFileType::store()\n"));
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
);
662 strcpy(head
->suffix
, _suffixList
.front().c_str());
664 dest
= static_cast<UChar8
*>(buffer
+ headSize
);
668 dataSize
= static_cast<unsigned long>(
669 storeData(pImage
, dest
, memSize
- headSize
));
672 dest
= static_cast<UChar8
*>(buffer
+ headSize
+ dataSize
);
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];
690 for (i = 0; i < l; i++)
696 FFATAL (("Invalid Attachment in ImageFileType::store()\n"));
702 FDEBUG (( "Store image data: %lu (%lu/%lu/%lu)\n",
703 headSize
+ dataSize
+ attachmentSize
, headSize
, dataSize
,
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
719 UInt64
ImageFileType::maxBufferSize(Image
const * pImage
)
722 unsigned long size
, attachmentSize
;
723 unsigned long imageSize
= pImage
->getSize(), headSize
= sizeof(Head
);
725 std::map
<std::string
, std::string
>::const_iterator aI
;
729 // get attachment size
731 ImageGenericAttPtr att=ImageGenericAttPtr::dcast(
732 const_cast<Image*>(image.getCPtr())->findAttachment(
733 ImageGenericAtt::getClassType().getGroupId()));
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;
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
));
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
;