fixed: auto_ptr -> unique_ptr
[opensg.git] / Source / System / Image / FileIO / OSGDATImageFileType.cpp
blob90ac2eaf3fc32ebcd248ac5a1109643e82b3d314
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 //-------------------------------
40 // Includes
41 //-------------------------------
43 #include <cstdlib>
44 #include <cstdio>
46 #include "OSGConfig.h"
48 #include <iostream>
49 #include <fstream>
51 #include "OSGLog.h"
52 #include "OSGImageFileHandler.h"
53 #include "OSGPathHandler.h"
54 #include "OSGFileSystem.h"
55 #include "OSGZStream.h"
57 #include "OSGDATImageFileType.h"
59 // Static Class Varible implementations:
61 static const OSG::Char8 *suffixArray[] =
63 "dat"
67 OSG_BEGIN_NAMESPACE
69 /*! \class DATImageFileType
71 Image File Type to read/write and store/restore Image objects as
72 PNM/RAW data.
74 All the type specific code is included in the class. Does
75 not depend on external libs.
81 DATImageFileType DATImageFileType::_the("image/x-dat",
82 suffixArray,
83 sizeof(suffixArray) );
85 std::map<std::string,
86 DATImageFileType::KeyType > DATImageFileType::_keyStrMap;
88 std::map<std::string,
89 DATImageFileType::FormatDesc> DATImageFileType::_formatStrMap;
93 //-------------------------------------------------------------------------
95 /*! Tries to fill the image object with the data read from
96 the given fileName. Returns true on success.
99 bool DATImageFileType::read( Image *image,
100 const Char8 *fileName)
102 bool retCode = false;
104 std::ifstream inDat(fileName), inVolS;
105 std::istream *inVol;
106 std::string keyStr, objectFileName;
107 const UInt32 lineBufferSize = 1024;
108 Char8 *value, *keySepPos, lineBuffer[lineBufferSize];
109 const Char8 keySep = ':';
110 int fileOffset, keyL, valueL;
111 std::map<std::string, KeyType>::iterator keyI;
112 std::map<std::string, FormatDesc>::iterator formatI;
113 KeyType key;
114 Image::Type formatType;
115 UInt32 channel = 1;
116 UInt32 res[3];
117 UInt32 dataSize = 0;
118 Image::PixelFormat pixelFormat = Image::OSG_L_PF;
119 char *dataBuffer = 0;
120 bool needConversion = false;
121 // default endian type is big endian
122 bool big_endian = true;
124 res[0] = res[1] = res[2] = 0;
125 fileOffset = 0;
126 formatType = Image::OSG_INVALID_IMAGEDATATYPE;
127 dataSize = 0;
128 dataBuffer = 0;
130 initTypeMap();
132 // read the data file
133 for(lineBuffer[0] = 0;
134 inDat.getline(lineBuffer, lineBufferSize);
135 lineBuffer[0] = 0)
137 if((keySepPos = strchr(lineBuffer,keySep)))
139 keyL = keySepPos - lineBuffer;
140 keyStr.assign( lineBuffer, keyL );
141 keyI = _keyStrMap.find(keyStr);
142 key = ((keyI == _keyStrMap.end()) ? UNKNOWN_KT : keyI->second);
143 value = keySepPos + 1;
145 while (value && isspace(*value))
146 value++;
148 valueL = int(strlen(value));
150 while (isspace(value[valueL-1]))
151 value[--valueL] = 0;
153 switch (key)
155 case OBJECT_FILE_NAME_KT:
156 objectFileName = value;
157 image->setAttachmentField ( keyStr, value );
158 break;
159 case CHANNEL_KT:
160 sscanf ( value, "%u", &(channel) );
161 image->setAttachmentField ( keyStr, value );
162 break;
163 case RESOLUTION_KT:
164 sscanf ( value, "%u %u %u",
165 &(res[0]), &(res[1]), &(res[2]));
166 image->setAttachmentField ( keyStr, value );
167 break;
168 case FORMAT_KT:
169 formatI = _formatStrMap.find(value);
170 if (formatI != _formatStrMap.end())
172 formatType = formatI->second.type;
174 else
176 formatType = Image::OSG_INVALID_IMAGEDATATYPE;
178 image->setAttachmentField ( keyStr, value );
179 break;
180 case ENDIAN_KT:
181 if(!strcmp(value, "LITTLE"))
182 big_endian = false;
183 image->setAttachmentField ( keyStr, value );
184 break;
185 case FILE_OFFSET_KT:
186 sscanf ( value, "%d", &fileOffset );
187 image->setAttachmentField ( keyStr, value );
188 break;
189 case UNKNOWN_KT:
190 FNOTICE (( "Uknown DAT file key: >%s<\n",
191 keyStr.c_str() ));
192 image->setAttachmentField ( keyStr, value );
193 break;
194 case SLICE_THICKNESS_KT:
195 default:
196 image->setAttachmentField ( keyStr, value );
197 break;
200 else
202 FINFO (("Skip DAT line\n"));
206 // set pixelformat
207 switch (channel)
209 case 4:
210 pixelFormat = Image::OSG_RGBA_PF;
211 break;
212 case 3:
213 pixelFormat = Image::OSG_RGB_PF;
214 break;
215 case 2:
216 pixelFormat = Image::OSG_LA_PF;
217 break;
218 default:
219 pixelFormat = Image::OSG_L_PF;
220 break;
223 // check the setting and read the raw vol data
224 if (objectFileName.empty() == false)
226 if((res[0] > 0) && (res[1] > 0) && (res[2] > 0))
228 if(formatType != Image::OSG_INVALID_IMAGEDATATYPE)
230 inVolS.open(objectFileName.c_str(),
231 std::ios::in | std::ios::binary);
233 if (inVolS.fail() && ImageFileHandler::the()->getPathHandler())
235 // Try to find the file in the search path
236 inVolS.clear(); // reset the error state
238 PathHandler *ph =
239 ImageFileHandler::the()->getPathHandler();
241 inVolS.open(ph->findFile(objectFileName.c_str()).c_str(),
242 std::ios::in | std::ios::binary );
245 if(inVolS.fail())
247 // Maybe compressed and name not changed?
248 std::string gzname = objectFileName + ".gz";
250 inVolS.clear(); // reset the error state
252 inVolS.open(gzname.c_str(),
253 std::ios::in | std::ios::binary );
255 if(inVolS.fail() &&
256 ImageFileHandler::the()->getPathHandler())
258 // Try to find the file in the search path
259 inVolS.clear(); // reset the error state
261 PathHandler *ph =
262 ImageFileHandler::the()->getPathHandler();
264 inVolS.open(ph->findFile(gzname.c_str()).c_str(),
265 std::ios::in | std::ios::binary );
269 if(inVolS.good())
271 #ifdef OSG_WITH_ZLIB
272 zip_istream *unzipper = NULL;
273 #endif
275 image->set(pixelFormat,
276 res[0], res[1], res[2],
277 1, 1, 0.0, 0,
278 formatType);
280 image->clear();
282 dataSize = image->getSize();
284 UInt32 fileDataSize = dataSize;
286 if(isGZip(inVolS))
288 #ifdef OSG_WITH_ZLIB
289 unzipper = new zip_istream(inVolS);
290 inVol = unzipper;
291 #else
292 SFATAL << "Compressed streams are not supported! "
293 << "Configure with --enable-png "
294 << "--with-png=DIR options." << std::endl;
295 #endif
297 else
299 inVol = &inVolS;
301 // get length of the stream.
302 inVol->seekg(0, std::ios::end);
303 UInt64 length = inVol->tellg();
304 inVol->seekg(0, std::ios::beg);
306 if(length < dataSize - fileOffset)
308 // correct dataSize.
309 fileDataSize = length;
310 FWARNING (( "RAW file length to small!\n" ));
312 else if(length > dataSize - fileOffset)
314 FWARNING (( "RAW file length to big!\n" ));
318 if(needConversion)
320 dataBuffer = new char [ dataSize ];
322 else
324 dataBuffer =
325 reinterpret_cast<char *>(image->editData());
328 if(fileOffset != 0)
329 inVol->ignore (fileOffset);
331 inVol->read ( dataBuffer, fileDataSize );
333 #ifdef OSG_WITH_ZLIB
334 if(unzipper != NULL)
335 delete unzipper;
336 #endif
338 else
340 FWARNING (( "Can not open %s image data\n",
341 objectFileName.c_str() ));
344 else
346 FWARNING (( "Invalid/Missing DAT Format\n" ));
349 else
351 FWARNING (( "Invalid/Missing DAT Resolution\n" ));
354 else
356 FWARNING (( "Invalid/Missing DAT ObjectFileName\n" ));
359 // check/reformat vol data
360 if (dataSize && dataBuffer)
362 // check host endian type
363 UInt16 word = 0x0001;
364 UInt8 *byte = reinterpret_cast<UInt8 *>(&word);
365 bool host_big_endian = byte[0] ? false : true;
367 if(big_endian != host_big_endian)
368 image->swapDataEndian();
370 if (needConversion)
372 FLOG (("DAT-Data convert not impl. yet !\n"));
374 switch (formatType)
376 case Image::OSG_UINT8_IMAGEDATA:
377 break;
378 case Image::OSG_UINT16_IMAGEDATA:
379 break;
380 case Image::OSG_UINT32_IMAGEDATA:
381 break;
382 case Image::OSG_FLOAT32_IMAGEDATA:
383 break;
384 default:
389 else
391 retCode = true;
396 /* TODO
397 std::ifstream in(fileName);
398 Head head;
399 void *headData = (void*)(&head);
400 unsigned dataSize, headSize = sizeof(Head);
402 if ( in &&
403 in.read(static_cast<char *>(headData),
404 headSize) && head.netToHost() &&
405 image.set ( Image::PixelFormat(head.pixelFormat),
406 head.width, head.height, head.depth, head.mipmapCount,
407 head.frameCount, float(head.frameDelay) / 1000.0) &&
408 (dataSize = image.getSize()) &&
409 in.read((char *)(image.getData()), dataSize ))
410 retCode = true;
411 else
412 retCode = false;
415 return retCode;
418 //-------------------------------------------------------------------------
419 /*! Tries to write the image object to the given fileName.
420 Returns true on success.
422 bool DATImageFileType::write(const Image *image,
423 const Char8 *fileName)
425 initTypeMap();
427 // ok we write always in big endian.
428 #if BYTE_ORDER == LITTLE_ENDIAN
429 Image *pSwapImage = const_cast<Image *>(&(*image));
431 pSwapImage->swapDataEndian();
432 #endif
434 std::ofstream dat(fileName, std::ios::binary);
436 if(!dat)
438 SWARNING << "DATImageFileType::write : Can not open output stream "
439 << "for file '"
440 << fileName
441 << "'!"
442 << std::endl;
444 return false;
447 Real64 sT[3];
448 sT[0] = sT[1] = sT[2] = 1.0;
450 const std::string *attr = image->findAttachmentField("SliceThickness");
452 if(attr != NULL)
453 sscanf(attr->c_str(), "%lf %lf %lf", &sT[0], &sT[1], &sT[2]);
455 std::string format = "UCHAR";
457 for(std::map<std::string, FormatDesc>::iterator it = _formatStrMap.begin();
458 it != _formatStrMap.end();
459 ++it)
461 if((*it).second.type == image->getDataType())
463 format = (*it).first;
464 break;
468 std::string basename = fileName;
469 std::string::size_type i = basename.rfind(".");
471 if(i != std::string::npos)
472 basename = basename.substr(0, i);
474 basename += ".raw";
476 std::string name = basename;
478 i = name.rfind("/");
480 // on windows also a / is possible!
481 #if defined(WIN32)
482 if(i == std::string::npos)
483 i = name.rfind("\\");
484 #endif
486 if(i != std::string::npos)
487 name = name.substr(i+1);
489 dat << "ObjectFileName: " << name << "\n";
490 dat << "TaggedFileName: ---\n";
491 dat << "Resolution: " << image->getWidth() << " " << image->getHeight()
492 << " " << image->getDepth() << "\n";
493 dat << "SliceThickness: " << sT[0] << " " << sT[1] << " " << sT[2] << "\n";
494 dat << "Format: " << format << "\n";
495 dat << "NbrTags: 0\n";
496 dat << "ObjectType: TEXTURE_VOLUME_OBJECT\n";
497 dat << "ObjectModel: DENSITY\n";
498 dat << "GridType: EQUIDISTANT\n";
500 if(image->getBpp() > 1)
501 dat << "Channel: " << image->getBpp() << "\n";
503 dat.close();
505 std::ofstream raw(basename.c_str(), std::ios::binary);
507 if(!raw)
509 SWARNING << "DATImageFileType::write : Can not open output stream "
510 << "for file '"
511 << basename
512 << "'!"
513 << std::endl;
515 return false;
518 raw.write (reinterpret_cast<const char *>(image->getData()),
519 image->getSize());
520 raw.close();
522 // restore to original endian
523 #if BYTE_ORDER == LITTLE_ENDIAN
524 pSwapImage->swapDataEndian();
525 #endif
528 ofstream out(fileName);
529 Head head;
530 const void *headData = (void*)(&head);
531 unsigned dataSize = image.getSize(), headSize = sizeof(Head);
533 head.pixelFormat = image.getPixelFormat();
534 head.width = image.getWidth();
535 head.height = image.getHeight();
536 head.depth = image.getDepth();
537 head.mipmapCount = image.getMipMapCount();
538 head.frameCount = image.getFrameCount();
539 head.frameDelay = short(image.getFrameDelay() * 1000.0);
540 head.hostToNet();
542 if ( out && out.write(static_cast<const char *>(headData), headSize) &&
543 dataSize &&
544 out.write((char *)(image.getData()), dataSize) )
545 retCode = true;
546 else
547 retCode = false;
550 return true;
554 //-------------------------------------------------------------------------
555 /*! Tries to restore the image data from the given memblock.
556 Returns the amount of data read.
559 UInt64 DATImageFileType::restoreData( Image *image,
560 const UChar8 *buffer,
561 Int32 OSG_CHECK_ARG(memSize)) const
563 image->setData(buffer);
565 return image->getSize();
568 //-------------------------------------------------------------------------
569 /*! Tries to store the image data to the given memblock.
570 Returns the amount of data written.
573 UInt64 DATImageFileType::storeData(const Image *image,
574 UChar8 *buffer,
575 Int32 OSG_CHECK_ARG(memSize)) const
577 UInt32 dataSize = image->getSize();
578 const UChar8 *src = image->getData();
580 if(dataSize && src && buffer)
581 memcpy( buffer, src, dataSize);
583 return dataSize;
587 //-------------------------------------------------------------------------
588 /*! Constructor used for the singleton object
591 DATImageFileType::DATImageFileType(const Char8 *mimeType,
592 const Char8 *suffixArray[],
593 UInt16 suffixByteCount) :
594 Inherited(mimeType,
595 suffixArray,
596 suffixByteCount)
601 //-------------------------------------------------------------------------
602 /*! Destructor
605 DATImageFileType::~DATImageFileType(void)
609 //-------------------------------------------------------------------------
610 /*! Helper to initialize the type map;
613 void DATImageFileType::initTypeMap(void)
615 FormatDesc *desc;
617 if(_keyStrMap.empty())
619 _keyStrMap["ObjectFileName"] = OBJECT_FILE_NAME_KT;
620 _keyStrMap["Resolution"] = RESOLUTION_KT;
621 _keyStrMap["Channel"] = CHANNEL_KT;
622 _keyStrMap["SliceThickness"] = SLICE_THICKNESS_KT;
623 _keyStrMap["Format"] = FORMAT_KT;
624 _keyStrMap["Endian"] = ENDIAN_KT;
625 _keyStrMap["FileOffset"] = FILE_OFFSET_KT;
628 if(_formatStrMap.empty())
630 desc = &(_formatStrMap["UCHAR"]);
631 desc->type = Image::OSG_UINT8_IMAGEDATA;
632 desc->bpv = 1;
633 desc->pixelFormat = Image::OSG_L_PF;
634 desc->needConversion = false;
636 desc = &(_formatStrMap["USHORT"]);
637 desc->type = Image::OSG_UINT16_IMAGEDATA;
638 desc->bpv = 2;
639 desc->pixelFormat = Image::OSG_L_PF;
640 desc->needConversion = false;
642 desc = &(_formatStrMap["UINT"]);
643 desc->type = Image::OSG_UINT32_IMAGEDATA;
644 desc->bpv = 4; // TODO; is this right ?
645 desc->pixelFormat = Image::OSG_L_PF;
646 desc->needConversion = false;
648 desc = &(_formatStrMap["ULONG"]);
649 desc->type = Image::OSG_UINT32_IMAGEDATA;
650 desc->bpv = 4;
651 desc->pixelFormat = Image::OSG_L_PF;
652 desc->needConversion = false;
654 desc = &(_formatStrMap["FLOAT"]);
655 desc->type = Image::OSG_FLOAT32_IMAGEDATA;
656 desc->bpv = 4;
657 desc->pixelFormat = Image::OSG_L_PF;
658 desc->needConversion = false;
660 desc = &(_formatStrMap["DOUBLE"]);
661 // we have no OSG_FLOAT64_IMAGEDATA
662 desc->type = Image::OSG_FLOAT32_IMAGEDATA;
663 desc->bpv = 8;
664 desc->pixelFormat = Image::OSG_L_PF;
665 desc->needConversion = false;
669 OSG_END_NAMESPACE