PageRenderTime 43ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 1ms

/Source/System/Image/FileIO/OSGDATImageFileType.cpp

https://github.com/msteners/OpenSGDevMaster_Toolbox
C++ | 667 lines | 504 code | 73 blank | 90 comment | 50 complexity | 6b90ed3da19fad9391badee111e99414 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. //-------------------------------
  39. // Includes
  40. //-------------------------------
  41. #include <cstdlib>
  42. #include <cstdio>
  43. #include "OSGConfig.h"
  44. #include <iostream>
  45. #include <fstream>
  46. #include "OSGLog.h"
  47. #include "OSGImageFileHandler.h"
  48. #include "OSGPathHandler.h"
  49. #include "OSGFileSystem.h"
  50. #include "OSGZStream.h"
  51. #include "OSGDATImageFileType.h"
  52. OSG_USING_NAMESPACE
  53. /*! \class OSG::DATImageFileType
  54. \ingroup GrpSystemImage
  55. Image File Type to read/write and store/restore Image objects as
  56. PNM/RAW data.
  57. All the type specific code is included in the class. Does
  58. not depend on external libs.
  59. */
  60. // Static Class Varible implementations:
  61. static const Char8 *suffixArray[] =
  62. {
  63. "dat"
  64. };
  65. DATImageFileType DATImageFileType::_the("image/x-dat",
  66. suffixArray,
  67. sizeof(suffixArray) );
  68. std::map<std::string,
  69. DATImageFileType::KeyType > DATImageFileType::_keyStrMap;
  70. std::map<std::string,
  71. DATImageFileType::FormatDesc> DATImageFileType::_formatStrMap;
  72. //-------------------------------------------------------------------------
  73. /*! Tries to fill the image object with the data read from
  74. the given fileName. Returns true on success.
  75. */
  76. bool DATImageFileType::read( Image *image,
  77. const Char8 *fileName)
  78. {
  79. bool retCode = false;
  80. std::ifstream inDat(fileName), inVolS;
  81. std::istream *inVol;
  82. std::string keyStr, objectFileName;
  83. const UInt32 lineBufferSize = 1024;
  84. Char8 *value, *keySepPos, lineBuffer[lineBufferSize];
  85. const Char8 keySep = ':';
  86. int fileOffset, keyL, valueL;
  87. std::map<std::string, KeyType>::iterator keyI;
  88. std::map<std::string, FormatDesc>::iterator formatI;
  89. KeyType key;
  90. Image::Type formatType;
  91. UInt32 channel = 1;
  92. UInt32 res[3];
  93. UInt32 dataSize = 0;
  94. Image::PixelFormat pixelFormat = Image::OSG_L_PF;
  95. char *dataBuffer = 0;
  96. bool needConversion = false;
  97. // default endian type is big endian
  98. bool big_endian = true;
  99. res[0] = res[1] = res[2] = 0;
  100. fileOffset = 0;
  101. formatType = Image::OSG_INVALID_IMAGEDATATYPE;
  102. dataSize = 0;
  103. dataBuffer = 0;
  104. initTypeMap();
  105. // read the data file
  106. for(lineBuffer[0] = 0;
  107. inDat.getline(lineBuffer, lineBufferSize);
  108. lineBuffer[0] = 0)
  109. {
  110. if((keySepPos = strchr(lineBuffer,keySep)))
  111. {
  112. keyL = keySepPos - lineBuffer;
  113. keyStr.assign( lineBuffer, keyL );
  114. keyI = _keyStrMap.find(keyStr);
  115. key = ((keyI == _keyStrMap.end()) ? UNKNOWN_KT : keyI->second);
  116. value = keySepPos + 1;
  117. while (value && isspace(*value))
  118. value++;
  119. valueL = strlen(value);
  120. while (isspace(value[valueL-1]))
  121. value[--valueL] = 0;
  122. switch (key)
  123. {
  124. case OBJECT_FILE_NAME_KT:
  125. objectFileName = value;
  126. image->setAttachmentField ( keyStr, value );
  127. break;
  128. case CHANNEL_KT:
  129. sscanf ( value, "%d", &(channel) );
  130. image->setAttachmentField ( keyStr, value );
  131. break;
  132. case RESOLUTION_KT:
  133. sscanf ( value, "%d %d %d",
  134. &(res[0]), &(res[1]), &(res[2]));
  135. image->setAttachmentField ( keyStr, value );
  136. break;
  137. case FORMAT_KT:
  138. formatI = _formatStrMap.find(value);
  139. if (formatI != _formatStrMap.end())
  140. {
  141. formatType = formatI->second.type;
  142. }
  143. else
  144. {
  145. formatType = Image::OSG_INVALID_IMAGEDATATYPE;
  146. }
  147. image->setAttachmentField ( keyStr, value );
  148. break;
  149. case ENDIAN_KT:
  150. if(!strcmp(value, "LITTLE"))
  151. big_endian = false;
  152. image->setAttachmentField ( keyStr, value );
  153. break;
  154. case FILE_OFFSET_KT:
  155. sscanf ( value, "%d", &fileOffset );
  156. image->setAttachmentField ( keyStr, value );
  157. break;
  158. case UNKNOWN_KT:
  159. FNOTICE (( "Uknown DAT file key: >%s<\n",
  160. keyStr.c_str() ));
  161. image->setAttachmentField ( keyStr, value );
  162. break;
  163. case SLICE_THICKNESS_KT:
  164. default:
  165. image->setAttachmentField ( keyStr, value );
  166. break;
  167. }
  168. }
  169. else
  170. {
  171. FINFO (("Skip DAT line\n"));
  172. }
  173. }
  174. // set pixelformat
  175. switch (channel)
  176. {
  177. case 4:
  178. pixelFormat = Image::OSG_RGBA_PF;
  179. break;
  180. case 3:
  181. pixelFormat = Image::OSG_RGB_PF;
  182. break;
  183. case 2:
  184. pixelFormat = Image::OSG_LA_PF;
  185. break;
  186. default:
  187. pixelFormat = Image::OSG_L_PF;
  188. break;
  189. }
  190. // check the setting and read the raw vol data
  191. if (objectFileName.empty() == false)
  192. {
  193. if((res[0] > 0) && (res[1] > 0) && (res[2] > 0))
  194. {
  195. if(formatType != Image::OSG_INVALID_IMAGEDATATYPE)
  196. {
  197. inVolS.open(objectFileName.c_str(),
  198. std::ios::in | std::ios::binary);
  199. if (inVolS.fail() && ImageFileHandler::the()->getPathHandler())
  200. {
  201. // Try to find the file in the search path
  202. inVolS.clear(); // reset the error state
  203. PathHandler *ph =
  204. ImageFileHandler::the()->getPathHandler();
  205. inVolS.open(ph->findFile(objectFileName.c_str()).c_str(),
  206. std::ios::in | std::ios::binary );
  207. }
  208. if(inVolS.fail())
  209. {
  210. // Maybe compressed and name not changed?
  211. std::string gzname = objectFileName + ".gz";
  212. inVolS.clear(); // reset the error state
  213. inVolS.open(gzname.c_str(),
  214. std::ios::in | std::ios::binary );
  215. if(inVolS.fail() &&
  216. ImageFileHandler::the()->getPathHandler())
  217. {
  218. // Try to find the file in the search path
  219. inVolS.clear(); // reset the error state
  220. PathHandler *ph =
  221. ImageFileHandler::the()->getPathHandler();
  222. inVolS.open(ph->findFile(gzname.c_str()).c_str(),
  223. std::ios::in | std::ios::binary );
  224. }
  225. }
  226. if(inVolS.good())
  227. {
  228. #ifdef OSG_WITH_ZLIB
  229. zip_istream *unzipper = NULL;
  230. #endif
  231. image->set(pixelFormat,
  232. res[0], res[1], res[2],
  233. 1, 1, 0.0, 0,
  234. formatType);
  235. image->clear();
  236. dataSize = image->getSize();
  237. UInt32 fileDataSize = dataSize;
  238. if(isGZip(inVolS))
  239. {
  240. #ifdef OSG_WITH_ZLIB
  241. unzipper = new zip_istream(inVolS);
  242. inVol = unzipper;
  243. #else
  244. SFATAL << "Compressed streams are not supported! "
  245. << "Configure with --enable-png "
  246. << "--with-png=DIR options." << std::endl;
  247. #endif
  248. }
  249. else
  250. {
  251. inVol = &inVolS;
  252. // get length of the stream.
  253. inVol->seekg(0, std::ios::end);
  254. UInt64 length = inVol->tellg();
  255. inVol->seekg(0, std::ios::beg);
  256. if(length < dataSize - fileOffset)
  257. {
  258. // correct dataSize.
  259. fileDataSize = length;
  260. FWARNING (( "RAW file length to small!\n" ));
  261. }
  262. else if(length > dataSize - fileOffset)
  263. {
  264. FWARNING (( "RAW file length to big!\n" ));
  265. }
  266. }
  267. if(needConversion)
  268. {
  269. dataBuffer = new char [ dataSize ];
  270. }
  271. else
  272. {
  273. dataBuffer =
  274. reinterpret_cast<char *>(image->editData());
  275. }
  276. if(fileOffset != 0)
  277. inVol->ignore (fileOffset);
  278. inVol->read ( dataBuffer, fileDataSize );
  279. #ifdef OSG_WITH_ZLIB
  280. if(unzipper != NULL)
  281. delete unzipper;
  282. #endif
  283. }
  284. else
  285. {
  286. FWARNING (( "Can not open %s image data\n",
  287. objectFileName.c_str() ));
  288. }
  289. }
  290. else
  291. {
  292. FWARNING (( "Invalid/Missing DAT Format\n" ));
  293. }
  294. }
  295. else
  296. {
  297. FWARNING (( "Invalid/Missing DAT Resolution\n" ));
  298. }
  299. }
  300. else
  301. {
  302. FWARNING (( "Invalid/Missing DAT ObjectFileName\n" ));
  303. }
  304. // check/reformat vol data
  305. if (dataSize && dataBuffer)
  306. {
  307. // check host endian type
  308. UInt16 word = 0x0001;
  309. UInt8 *byte = reinterpret_cast<UInt8 *>(&word);
  310. bool host_big_endian = byte[0] ? false : true;
  311. if(big_endian != host_big_endian)
  312. image->swapDataEndian();
  313. if (needConversion)
  314. {
  315. FLOG (("DAT-Data convert not impl. yet !\n"));
  316. {
  317. switch (formatType)
  318. {
  319. case Image::OSG_UINT8_IMAGEDATA:
  320. break;
  321. case Image::OSG_UINT16_IMAGEDATA:
  322. break;
  323. case Image::OSG_UINT32_IMAGEDATA:
  324. break;
  325. case Image::OSG_FLOAT32_IMAGEDATA:
  326. break;
  327. default:
  328. ;
  329. }
  330. }
  331. }
  332. else
  333. {
  334. retCode = true;
  335. }
  336. }
  337. /* TODO
  338. std::ifstream in(fileName);
  339. Head head;
  340. void *headData = (void*)(&head);
  341. unsigned dataSize, headSize = sizeof(Head);
  342. if ( in &&
  343. in.read(static_cast<char *>(headData),
  344. headSize) && head.netToHost() &&
  345. image.set ( Image::PixelFormat(head.pixelFormat),
  346. head.width, head.height, head.depth, head.mipmapCount,
  347. head.frameCount, float(head.frameDelay) / 1000.0) &&
  348. (dataSize = image.getSize()) &&
  349. in.read((char *)(image.getData()), dataSize ))
  350. retCode = true;
  351. else
  352. retCode = false;
  353. */
  354. return retCode;
  355. }
  356. //-------------------------------------------------------------------------
  357. /*! Tries to write the image object to the given fileName.
  358. Returns true on success.
  359. */
  360. bool DATImageFileType::write(const Image *image,
  361. const Char8 *fileName)
  362. {
  363. initTypeMap();
  364. // ok we write always in big endian.
  365. #if BYTE_ORDER == LITTLE_ENDIAN
  366. Image *pSwapImage = const_cast<Image *>(&(*image));
  367. pSwapImage->swapDataEndian();
  368. #endif
  369. std::ofstream dat(fileName, std::ios::binary);
  370. if(!dat)
  371. {
  372. SWARNING << "DATImageFileType::write : Can not open output stream "
  373. << "for file '"
  374. << fileName
  375. << "'!"
  376. << std::endl;
  377. return false;
  378. }
  379. Real64 sT[3];
  380. sT[0] = sT[1] = sT[2] = 1.0;
  381. const std::string *attr = image->findAttachmentField("SliceThickness");
  382. if(attr != NULL)
  383. sscanf(attr->c_str(), "%lf %lf %lf", &sT[0], &sT[1], &sT[2]);
  384. std::string format = "UCHAR";
  385. for(std::map<std::string, FormatDesc>::iterator it = _formatStrMap.begin();
  386. it != _formatStrMap.end();
  387. ++it)
  388. {
  389. if((*it).second.type == image->getDataType())
  390. {
  391. format = (*it).first;
  392. break;
  393. }
  394. }
  395. std::string basename = fileName;
  396. std::string::size_type i = basename.rfind(".");
  397. if(i != std::string::npos)
  398. basename = basename.substr(0, i);
  399. basename += ".raw";
  400. std::string name = basename;
  401. i = name.rfind("/");
  402. // on windows also a / is possible!
  403. #if defined(WIN32)
  404. if(i == std::string::npos)
  405. i = name.rfind("\\");
  406. #endif
  407. if(i != std::string::npos)
  408. name = name.substr(i+1);
  409. dat << "ObjectFileName: " << name << "\n";
  410. dat << "TaggedFileName: ---\n";
  411. dat << "Resolution: " << image->getWidth() << " " << image->getHeight()
  412. << " " << image->getDepth() << "\n";
  413. dat << "SliceThickness: " << sT[0] << " " << sT[1] << " " << sT[2] << "\n";
  414. dat << "Format: " << format << "\n";
  415. dat << "NbrTags: 0\n";
  416. dat << "ObjectType: TEXTURE_VOLUME_OBJECT\n";
  417. dat << "ObjectModel: DENSITY\n";
  418. dat << "GridType: EQUIDISTANT\n";
  419. if(image->getBpp() > 1)
  420. dat << "Channel: " << image->getBpp() << "\n";
  421. dat.close();
  422. std::ofstream raw(basename.c_str(), std::ios::binary);
  423. if(!raw)
  424. {
  425. SWARNING << "DATImageFileType::write : Can not open output stream "
  426. << "for file '"
  427. << basename
  428. << "'!"
  429. << std::endl;
  430. return false;
  431. }
  432. raw.write (reinterpret_cast<const char *>(image->getData()),
  433. image->getSize());
  434. raw.close();
  435. // restore to original endian
  436. #if BYTE_ORDER == LITTLE_ENDIAN
  437. pSwapImage->swapDataEndian();
  438. #endif
  439. /*
  440. ofstream out(fileName);
  441. Head head;
  442. const void *headData = (void*)(&head);
  443. unsigned dataSize = image.getSize(), headSize = sizeof(Head);
  444. head.pixelFormat = image.getPixelFormat();
  445. head.width = image.getWidth();
  446. head.height = image.getHeight();
  447. head.depth = image.getDepth();
  448. head.mipmapCount = image.getMipMapCount();
  449. head.frameCount = image.getFrameCount();
  450. head.frameDelay = short(image.getFrameDelay() * 1000.0);
  451. head.hostToNet();
  452. if ( out && out.write(static_cast<const char *>(headData), headSize) &&
  453. dataSize &&
  454. out.write((char *)(image.getData()), dataSize) )
  455. retCode = true;
  456. else
  457. retCode = false;
  458. */
  459. return true;
  460. }
  461. //-------------------------------------------------------------------------
  462. /*! Tries to restore the image data from the given memblock.
  463. Returns the amount of data read.
  464. */
  465. UInt64 DATImageFileType::restoreData( Image *image,
  466. const UChar8 *buffer,
  467. Int32 OSG_CHECK_ARG(memSize))
  468. {
  469. image->setData(buffer);
  470. return image->getSize();
  471. }
  472. //-------------------------------------------------------------------------
  473. /*! Tries to store the image data to the given memblock.
  474. Returns the amount of data written.
  475. */
  476. UInt64 DATImageFileType::storeData(const Image *image,
  477. UChar8 *buffer,
  478. Int32 OSG_CHECK_ARG(memSize))
  479. {
  480. UInt32 dataSize = image->getSize();
  481. const UChar8 *src = image->getData();
  482. if(dataSize && src && buffer)
  483. memcpy( buffer, src, dataSize);
  484. return dataSize;
  485. }
  486. //-------------------------------------------------------------------------
  487. /*! Constructor used for the singleton object
  488. */
  489. DATImageFileType::DATImageFileType(const Char8 *mimeType,
  490. const Char8 *suffixArray[],
  491. UInt16 suffixByteCount) :
  492. Inherited(mimeType,
  493. suffixArray,
  494. suffixByteCount)
  495. {
  496. }
  497. //-------------------------------------------------------------------------
  498. /*! Destructor
  499. */
  500. DATImageFileType::~DATImageFileType(void)
  501. {
  502. }
  503. //-------------------------------------------------------------------------
  504. /*! Helper to initialize the type map;
  505. */
  506. void DATImageFileType::initTypeMap(void)
  507. {
  508. FormatDesc *desc;
  509. if(_keyStrMap.empty())
  510. {
  511. _keyStrMap["ObjectFileName"] = OBJECT_FILE_NAME_KT;
  512. _keyStrMap["Resolution"] = RESOLUTION_KT;
  513. _keyStrMap["Channel"] = CHANNEL_KT;
  514. _keyStrMap["SliceThickness"] = SLICE_THICKNESS_KT;
  515. _keyStrMap["Format"] = FORMAT_KT;
  516. _keyStrMap["Endian"] = ENDIAN_KT;
  517. _keyStrMap["FileOffset"] = FILE_OFFSET_KT;
  518. }
  519. if(_formatStrMap.empty())
  520. {
  521. desc = &(_formatStrMap["UCHAR"]);
  522. desc->type = Image::OSG_UINT8_IMAGEDATA;
  523. desc->bpv = 1;
  524. desc->pixelFormat = Image::OSG_L_PF;
  525. desc->needConversion = false;
  526. desc = &(_formatStrMap["USHORT"]);
  527. desc->type = Image::OSG_UINT16_IMAGEDATA;
  528. desc->bpv = 2;
  529. desc->pixelFormat = Image::OSG_L_PF;
  530. desc->needConversion = false;
  531. desc = &(_formatStrMap["UINT"]);
  532. desc->type = Image::OSG_UINT32_IMAGEDATA;
  533. desc->bpv = 4; // TODO; is this right ?
  534. desc->pixelFormat = Image::OSG_L_PF;
  535. desc->needConversion = false;
  536. desc = &(_formatStrMap["ULONG"]);
  537. desc->type = Image::OSG_UINT32_IMAGEDATA;
  538. desc->bpv = 4;
  539. desc->pixelFormat = Image::OSG_L_PF;
  540. desc->needConversion = false;
  541. desc = &(_formatStrMap["FLOAT"]);
  542. desc->type = Image::OSG_FLOAT32_IMAGEDATA;
  543. desc->bpv = 4;
  544. desc->pixelFormat = Image::OSG_L_PF;
  545. desc->needConversion = false;
  546. desc = &(_formatStrMap["DOUBLE"]);
  547. // we have no OSG_FLOAT64_IMAGEDATA
  548. desc->type = Image::OSG_FLOAT32_IMAGEDATA;
  549. desc->bpv = 8;
  550. desc->pixelFormat = Image::OSG_L_PF;
  551. desc->needConversion = false;
  552. }
  553. }