PageRenderTime 27ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/Source/System/Image/OSGImageFileType.cpp

https://github.com/msteners/OpenSGDevMaster_Toolbox
C++ | 782 lines | 426 code | 142 blank | 214 comment | 39 complexity | 4180c54db4fc847e41df2b0a00112477 MD5 | raw file
Possible License(s): LGPL-2.0, BSD-3-Clause
  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. \*---------------------------------------------------------------------------*/
  38. // System declarations
  39. #include "OSGConfig.h"
  40. #include <iostream>
  41. // Application declarations
  42. // to get ntons/ntohs
  43. // Class declarations
  44. #include "OSGImageFileType.h"
  45. #include "OSGImageFileHandler.h"
  46. #include "OSGImageGenericAtt.h"
  47. #include "OSGLog.h"
  48. OSG_USING_NAMESPACE
  49. ImageBlockAccessor::~ImageBlockAccessor(void)
  50. {
  51. _pGeoRef = NULL;
  52. }
  53. ImageBlockAccessor::ImageBlockAccessor(void) :
  54. _pGeoRef (NULL ),
  55. _vSize (0, 0 ),
  56. _eImgType (Image::OSG_INVALID_IMAGEDATATYPE),
  57. _eImgFormat (Image::OSG_INVALID_PF ),
  58. _fNoDataValue(0 )
  59. {
  60. }
  61. Vec2i ImageBlockAccessor::getSize(void)
  62. {
  63. return _vSize;
  64. }
  65. Image::Type ImageBlockAccessor::getType(void)
  66. {
  67. return _eImgType;
  68. }
  69. Image::PixelFormat ImageBlockAccessor::getFormat(void)
  70. {
  71. return _eImgFormat;
  72. }
  73. GeoReferenceAttachment *ImageBlockAccessor::getGeoRef(void)
  74. {
  75. return _pGeoRef;
  76. }
  77. Real64 ImageBlockAccessor::getNoDataValue(void)
  78. {
  79. return _fNoDataValue;
  80. }
  81. BlockAccessWrapper::~BlockAccessWrapper(void)
  82. {
  83. _pImage = NULL;
  84. }
  85. bool BlockAccessWrapper::isOpen(void)
  86. {
  87. return (_pImage != NULL);
  88. }
  89. bool BlockAccessWrapper::readBlockA16(Vec2i vSampleOrigin,
  90. Int32 iTextureSize,
  91. UInt16 *pTarget,
  92. Int32 iTargetSizeBytes)
  93. {
  94. if(_pImage == NULL)
  95. return false;
  96. const UInt8 *pData = _pImage->getData();
  97. UInt8 *pDst = reinterpret_cast<UInt8 *>(pTarget);
  98. UInt32 destIdx = 0;
  99. Int32 xMin = vSampleOrigin.x();
  100. Int32 xMax = vSampleOrigin.x() + iTextureSize;
  101. Int32 yMin = vSampleOrigin.y();
  102. Int32 yMax = vSampleOrigin.y() + iTextureSize;
  103. for(Int32 y = yMin; y < yMax; y++)
  104. {
  105. for(Int32 x = xMin; x < xMax; x++)
  106. {
  107. for(Int32 i = 0; i < 2; i++)
  108. {
  109. if(y >= _pImage->getHeight() ||
  110. x >= _pImage->getWidth() )
  111. {
  112. pDst[destIdx] = 0;
  113. }
  114. else
  115. {
  116. pDst[destIdx] =
  117. pData[((y) * _pImage->getWidth() + x) * 2 + i];
  118. }
  119. destIdx++;
  120. }
  121. }
  122. destIdx += (iTextureSize - (xMax - xMin)) * 2;
  123. }
  124. return true;
  125. }
  126. bool BlockAccessWrapper::readBlockA16(Vec2i vSampleOrigin,
  127. Int32 iTextureSize,
  128. Int16 *pTarget,
  129. Int32 iTargetSizeBytes)
  130. {
  131. if(_pImage == NULL)
  132. return false;
  133. #if 0
  134. const UInt8 *pData = _pImage->getData();
  135. UInt8 *pDst = (UInt8 *) pTarget;
  136. UInt32 destIdx = 0;
  137. Int32 xMin = vSampleOrigin.x();
  138. Int32 xMax = vSampleOrigin.x() + iTextureSize;
  139. Int32 yMin = vSampleOrigin.y();
  140. Int32 yMax = vSampleOrigin.y() + iTextureSize;
  141. for(UInt32 y = yMin; y < yMax; y++)
  142. {
  143. for(UInt32 x = xMin; x < xMax; x++)
  144. {
  145. for(UInt32 i = 0; i < 2; i++)
  146. {
  147. if(y >= _pImage->getHeight() ||
  148. x >= _pImage->getWidth() )
  149. {
  150. pDst[destIdx] = 0;
  151. }
  152. else
  153. {
  154. pDst[destIdx] =
  155. pData[((y) * _pImage->getWidth() + x) * 2 + i];
  156. }
  157. destIdx++;
  158. }
  159. }
  160. destIdx += (iTextureSize - (xMax - xMin)) * 2;
  161. }
  162. #else
  163. const Int16 *pData = reinterpret_cast<const Int16 *>(_pImage->getData());
  164. UInt32 destIdx = 0;
  165. Int32 xMin = vSampleOrigin.x();
  166. Int32 xMax = vSampleOrigin.x() + iTextureSize;
  167. Int32 yMin = vSampleOrigin.y();
  168. Int32 yMax = vSampleOrigin.y() + iTextureSize;
  169. for(Int32 y = yMin; y < yMax; y++)
  170. {
  171. for(Int32 x = xMin; x < xMax; x++)
  172. {
  173. if(y >= _pImage->getHeight() ||
  174. x >= _pImage->getWidth() )
  175. {
  176. pTarget[destIdx] = 0;
  177. }
  178. else
  179. {
  180. pTarget[destIdx] =
  181. pData[((y) * _pImage->getWidth() + x)];
  182. }
  183. ++destIdx;
  184. }
  185. }
  186. #endif
  187. return true;
  188. }
  189. BlockAccessWrapper::BlockAccessWrapper(void) :
  190. Inherited( ),
  191. _pImage (NULL)
  192. {
  193. }
  194. void BlockAccessWrapper::open(const Char8 *szFilename)
  195. {
  196. _pImage = ImageFileHandler::the()->read(szFilename);
  197. if(_pImage != NULL)
  198. {
  199. _pGeoRef =
  200. dynamic_cast<GeoReferenceAttachment *>(
  201. _pImage->findAttachment(
  202. GeoReferenceAttachment::getClassType().getGroupId()));
  203. _vSize.setValues(_pImage->getWidth(),
  204. _pImage->getHeight());
  205. _eImgType = Image::Type (_pImage->getDataType ());
  206. _eImgFormat = Image::PixelFormat(_pImage->getPixelFormat());
  207. fprintf(stderr, "FOOO\n");
  208. _pImage->dump();
  209. }
  210. }
  211. /*! \class OSG::ImageFileType
  212. \ingroup GrpSystemImage
  213. */
  214. //-------------------------------------------------------------------------
  215. /*!
  216. Helper method to convert the Head block from net to host format
  217. */
  218. bool ImageFileType::Head::netToHost(void)
  219. {
  220. pixelFormat = osgntohs(pixelFormat);
  221. width = osgntohs(width);
  222. height = osgntohs(height);
  223. depth = osgntohs(depth);
  224. mipmapCount = osgntohs(mipmapCount);
  225. frameCount = osgntohs(frameCount);
  226. frameDelay = osgntohs(frameDelay);
  227. sideCount = osgntohs(sideCount);
  228. dataType = osgntohs(dataType);
  229. _reserved3 = 0;
  230. _reserved4 = 0;
  231. attachmentSize = osgntohs(attachmentSize);
  232. return true;
  233. }
  234. //-------------------------------------------------------------------------
  235. /*!
  236. Helper method to convert the Head block from host to net format
  237. */
  238. bool ImageFileType::Head::hostToNet(void)
  239. {
  240. pixelFormat = osghtons(pixelFormat);
  241. width = osghtons(width);
  242. height = osghtons(height);
  243. depth = osghtons(depth);
  244. mipmapCount = osghtons(mipmapCount);
  245. frameCount = osghtons(frameCount);
  246. frameDelay = osghtons(frameDelay);
  247. sideCount = osghtons(sideCount);
  248. dataType = osghtons(dataType);
  249. _reserved3 = 0;
  250. _reserved4 = 0;
  251. attachmentSize = osghtons(attachmentSize);
  252. return true;
  253. }
  254. //-------------------------------------------------------------------------
  255. /*! Get method for the mime type
  256. */
  257. const Char8 *ImageFileType::getMimeType(void) const
  258. {
  259. return _mimeType.c_str();
  260. }
  261. //-------------------------------------------------------------------------
  262. bool ImageFileType::read(Image *pImage, const Char8 *fileName)
  263. {
  264. std::ifstream is(fileName, std::ios::binary);
  265. if (is.good() == false)
  266. return false;
  267. return read(pImage, is, std::string());
  268. }
  269. //-------------------------------------------------------------------------
  270. bool ImageFileType::write(Image const * pImage, const Char8 *fileName)
  271. {
  272. std::ofstream os(fileName, std::ios::binary);
  273. if (os.good() == false)
  274. return false;
  275. return write(pImage, os, std::string());
  276. }
  277. //-------------------------------------------------------------------------
  278. /*! Get method for the suffix list container
  279. */
  280. const std::list<std::string> &ImageFileType::getSuffixList(void) const
  281. {
  282. return _suffixList;
  283. }
  284. //-------------------------------------------------------------------------
  285. bool ImageFileType::validateHeader(const Char8 *fileName, bool &implemented)
  286. {
  287. implemented = false;
  288. return true;
  289. }
  290. ImageBlockAccessorPtr ImageFileType::open(const Char8 *szFilename)
  291. {
  292. BlockAccessWrapperPtr returnValue(new BlockAccessWrapper);
  293. returnValue->open(szFilename);
  294. return returnValue;
  295. }
  296. //-------------------------------------------------------------------------
  297. /*!
  298. Tries to fill the image object with the data read from
  299. the given input stream. Returns true on success.
  300. */
  301. bool ImageFileType::read( Image *pImage,
  302. std::istream &is,
  303. const std::string &mimetype)
  304. {
  305. SWARNING << getMimeType()
  306. << " read from stream is not implemented"
  307. << endLog;
  308. return false;
  309. }
  310. //-------------------------------------------------------------------------
  311. /*!
  312. Tries to write the image object to the given output stream.
  313. Returns true on success.
  314. */
  315. bool ImageFileType::write(Image const *pImage,
  316. std::ostream &os,
  317. std::string const &mimetype)
  318. {
  319. SWARNING << getMimeType()
  320. << " write to stream is not implemented"
  321. << endLog;
  322. return false;
  323. }
  324. //-------------------------------------------------------------------------
  325. /*!
  326. Tries to determine the mime type of the data provided by an input stream
  327. by searching for magic bytes. Returns the mime type or an empty string
  328. when the function could not determine the mime type.
  329. */
  330. std::string ImageFileType::determineMimetypeFromStream(std::istream &is)
  331. {
  332. return std::string();
  333. }
  334. //-------------------------------------------------------------------------
  335. /*! Constructor which takes a suffix array and size to add the
  336. ImageFileType to the Singleton ImageFileHandler
  337. */
  338. ImageFileType::ImageFileType(const char *mimeType,
  339. const Char8 *suffixArray[],
  340. UInt16 suffixByteCount,
  341. UInt32 flags)
  342. : Inherited(flags)
  343. {
  344. Int32 suffixCount = suffixByteCount / sizeof(const Char8 *);
  345. Int32 i = 0;
  346. std::list<std::string>::iterator sI;
  347. if (!mimeType)
  348. {
  349. FFATAL (("ImageFileType without valid mimeType\n"));
  350. }
  351. _mimeType.assign(mimeType);
  352. _suffixList.resize(suffixCount);
  353. for(sI = _suffixList.begin(); sI != _suffixList.end(); sI++)
  354. {
  355. sI->assign(suffixArray[i++]);
  356. SINFO << "add image suffix: " << *sI << endLog;
  357. }
  358. ImageFileHandler::the()->addImageFileType(*this);
  359. }
  360. //-------------------------------------------------------------------------
  361. /*! Destructor
  362. */
  363. ImageFileType::~ImageFileType(void)
  364. {
  365. }
  366. //-------------------------------------------------------------------------
  367. /*! Abstract restore method. Should be overwriten by an concrete derived
  368. class. Tries to restore the image data from the given memblock.
  369. */
  370. UInt64 ImageFileType::restoreData( Image * ,
  371. const UChar8 *OSG_CHECK_ARG(buffer ),
  372. Int32 OSG_CHECK_ARG(memSize))
  373. {
  374. FWARNING(("ImageXFileType::restoreData() not impl. for mimeType %s\n",
  375. getMimeType()));
  376. return 0;
  377. }
  378. //-------------------------------------------------------------------------
  379. /*! Abstract restore method. Should be overwriten by an concrete derived
  380. class. Tries to store the given image data to the given memblock
  381. */
  382. UInt64 ImageFileType::storeData(Image const * ,
  383. UChar8 *OSG_CHECK_ARG(buffer ),
  384. Int32 OSG_CHECK_ARG(memSize))
  385. {
  386. FWARNING(("ImageXFileType::storeData() not impl. for mimeType %s\n",
  387. getMimeType()));
  388. return 0;
  389. }
  390. //-------------------------------------------------------------------------
  391. /*! Tries to restore the Imagedata from the given memblock. The buffer must
  392. include a ImageFileType::Head data block.
  393. */
  394. UInt64 ImageFileType::restore( Image *pImage,
  395. const UChar8 *buffer,
  396. Int32 memSize)
  397. {
  398. long imageSize, headSize = sizeof(Head);
  399. unsigned long size = 0, attachmentSize;
  400. Head head;
  401. const UChar8 *data = buffer ? (buffer + headSize) : 0;
  402. ImageFileType *type;
  403. std::string mimeType;
  404. Image::Type dataType;
  405. if((pImage != NULL) && (buffer != NULL) && (memSize >= headSize))
  406. {
  407. // Copy header. Otherwise netToHost would change the original
  408. // data structur.
  409. memcpy(&head,buffer,sizeof(Head));
  410. head.netToHost();
  411. mimeType =
  412. ImageFileHandler::the()->determineMimetypeFromSuffix(head.suffix);
  413. if((type = ImageFileHandler::the()->getFileType(mimeType.c_str(), 0)))
  414. {
  415. if (head.dataType)
  416. dataType = Image::Type(head.dataType);
  417. else
  418. dataType = Image::OSG_UINT8_IMAGEDATA;
  419. pImage->set(Image::PixelFormat(head.pixelFormat),
  420. head.width,
  421. head.height,
  422. head.depth,
  423. head.mipmapCount,
  424. head.frameCount,
  425. float(head.frameDelay) / 1000.0,
  426. 0,
  427. dataType,
  428. true,
  429. head.sideCount);
  430. imageSize = static_cast<unsigned long>(
  431. type->restoreData(pImage, data, memSize - headSize));
  432. attachmentSize = 0; // head->attachmentSize;
  433. /*
  434. if ((attachmentSize = head->attachmentSize))
  435. {
  436. attData = (char*)(buffer + headSize + imageSize);
  437. attKey = attData;
  438. attValue = 0;
  439. for (i = 0; i < (attachmentSize-1); i++) {
  440. if (attData[i] == 0)
  441. if (attKey) {
  442. attValue = &(attData[i+1]);
  443. image->setAttachmentField (attKey,attValue);
  444. attKey = attValue = 0;
  445. }
  446. else
  447. attKey = &(attData[i+1]);
  448. }
  449. if (attKey || attValue) {
  450. FFATAL (("Attachment restore error\n"));
  451. }
  452. }
  453. */
  454. size = headSize + imageSize + attachmentSize;
  455. FDEBUG (( "Restore image data: %lu (%lu/%lu/%lu)\n",
  456. size, headSize, imageSize, attachmentSize ));
  457. }
  458. else
  459. {
  460. imageSize = 0;
  461. FWARNING(("Can not restore image data, invalid mimeType: %s\n",
  462. mimeType.empty() == false ?
  463. mimeType.c_str() : "Unknown"));
  464. }
  465. }
  466. return size;
  467. }
  468. //-------------------------------------------------------------------------
  469. /*! Tries to store the raster data to the given mem block.
  470. Will include a ImageFileType::Head description and the data encoded
  471. as 'mimeType'
  472. */
  473. UInt64 ImageFileType::store(Image const *pImage,
  474. Char8 const *mimeType,
  475. UChar8 *buffer,
  476. Int32 memSize)
  477. {
  478. ImageFileType *type = ImageFileHandler::the()->getFileType(mimeType);
  479. return type ? type->store(pImage, buffer, memSize) : 0;
  480. }
  481. //-------------------------------------------------------------------------
  482. /*! Tries to store the raster data to the given mem block.
  483. Will include a ImageFileType::Head description for the derived
  484. concreate mimeType.
  485. */
  486. UInt64 ImageFileType::store(Image const *pImage,
  487. UChar8 *buffer,
  488. Int32 memSize)
  489. {
  490. Head *head;
  491. unsigned long dataSize = 0, headSize = sizeof(Head);
  492. unsigned long attachmentSize;
  493. UChar8 *dest;
  494. const UChar8 *src = pImage->getData();
  495. std::map<std::string, std::string>::const_iterator aI;
  496. std::string value;
  497. attachmentSize = 0;
  498. // get attachment size
  499. /*
  500. ImageGenericAttPtr att=ImageGenericAttPtr::dcast(
  501. const_cast<Image*>(image.getCPtr())->findAttachment(
  502. ImageGenericAtt::getClassType().getGroupId()));
  503. if(att != NULL)
  504. {
  505. for(i = 0; i < (att->getType().getNumFieldDescs()-1); ++i)
  506. {
  507. FieldDescription *fieldDesc=att->getType().getFieldDescription(i);
  508. Field *field=att->getField(i);
  509. if (fieldDesc && field)
  510. {
  511. field->getValueByStr(value);
  512. attachmentSize += strlen( fieldDesc->getName().str() ) + 1;
  513. attachmentSize += value.length() + 1;
  514. std::cout << fieldDesc->getName().str() << std::endl;
  515. std::cout << value << std::endl;
  516. }
  517. else
  518. {
  519. FFATAL (("Invalid Attachment in ImageFileType::store()\n"));
  520. }
  521. }
  522. }
  523. */
  524. if (buffer)
  525. {
  526. head = reinterpret_cast<Head *>(buffer);
  527. head->pixelFormat = pImage->getPixelFormat();
  528. head->width = pImage->getWidth();
  529. head->height = pImage->getHeight();
  530. head->depth = pImage->getDepth();
  531. head->mipmapCount = pImage->getMipMapCount();
  532. head->frameCount = pImage->getFrameCount();
  533. head->frameDelay = short(pImage->getFrameDelay() * 1000.0);
  534. head->sideCount = pImage->getSideCount();
  535. head->dataType = pImage->getDataType();
  536. head->attachmentSize = static_cast<unsigned short>(attachmentSize);
  537. head->hostToNet();
  538. strcpy(head->suffix, _suffixList.front().c_str());
  539. dest = static_cast<UChar8 *>(buffer + headSize);
  540. if(src)
  541. {
  542. dataSize = static_cast<unsigned long>(
  543. storeData(pImage, dest, memSize - headSize));
  544. }
  545. dest = static_cast<UChar8 *>(buffer + headSize + dataSize);
  546. /*
  547. if(att != NULL)
  548. {
  549. for(i = 0; i < (att->getType().getNumFieldDescs()-1); ++i)
  550. {
  551. FieldDescription *fieldDesc=att->getType().getFieldDescription(i);
  552. Field *field=att->getField(i);
  553. if (field && fieldDesc)
  554. {
  555. field->getValueByStr(value);
  556. l = strlen( fieldDesc->getName().str() );
  557. for (i = 0; i < l; i++)
  558. *dest++ = fieldDesc->getName().str()[i];
  559. *dest++ = 0;
  560. l = value.length();
  561. for (i = 0; i < l; i++)
  562. *dest++ = value[i];
  563. *dest++ = 0;
  564. }
  565. else
  566. {
  567. FFATAL (("Invalid Attachment in ImageFileType::store()\n"));
  568. }
  569. }
  570. }
  571. */
  572. FDEBUG (( "Store image data: %lu (%lu/%lu/%lu)\n",
  573. headSize + dataSize + attachmentSize, headSize, dataSize,
  574. attachmentSize ));
  575. }
  576. else
  577. {
  578. FFATAL (("Invalid buffer in ImageFileType::store()\n"));
  579. }
  580. return (headSize + dataSize + attachmentSize);
  581. }
  582. //-------------------------------------------------------------------------
  583. /*! Returns the max buffer size needed to store the Image (Head + mimeType
  584. specific data block)
  585. */
  586. UInt64 ImageFileType::maxBufferSize(Image const * pImage)
  587. {
  588. std::string value;
  589. unsigned long size, attachmentSize;
  590. unsigned long imageSize = pImage->getSize(), headSize = sizeof(Head);
  591. std::map<std::string, std::string>::const_iterator aI;
  592. attachmentSize = 0;
  593. // get attachment size
  594. /*
  595. ImageGenericAttPtr att=ImageGenericAttPtr::dcast(
  596. const_cast<Image*>(image.getCPtr())->findAttachment(
  597. ImageGenericAtt::getClassType().getGroupId()));
  598. if(att != NULL)
  599. {
  600. for(i = 0; i < (att->getType().getNumFieldDescs()-1); ++i)
  601. {
  602. FieldDescription *fieldDesc=att->getType().getFieldDescription(i);
  603. Field *field=att->getField(i);
  604. if (field && fieldDesc)
  605. {
  606. field->getValueByStr(value);
  607. attachmentSize += strlen( fieldDesc->getName().str() ) + 1;
  608. attachmentSize += value.length() + 1;
  609. }
  610. else
  611. {
  612. FFATAL (("Invalid Attachment in ImageFileType::maxBufferSize()\n"));
  613. }
  614. }
  615. }
  616. */
  617. size = headSize + imageSize + attachmentSize;
  618. FINFO (( "ImageFileType::maxBufferSize(): %lu (%lu/%lu/%lu)\n",
  619. size, headSize, imageSize, attachmentSize ));
  620. return size;
  621. }
  622. //-------------------------------------------------------------------------
  623. /*! The dump method just writes some object debugging info to the LOG stream
  624. */
  625. void ImageFileType::dump(void)
  626. {
  627. std::list<std::string>::iterator sI;
  628. SLOG << getMimeType();
  629. if(_suffixList.empty())
  630. {
  631. SLOG << ": Suffix: ";
  632. for(sI = _suffixList.begin(); sI != _suffixList.end(); sI++)
  633. {
  634. Log().stream(OSG::LOG_DEBUG) << sI->c_str() << " ";
  635. }
  636. }
  637. std::cerr << std::endl;
  638. }