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 //-------------------------------
41 //-------------------------------
46 #include "OSGConfig.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
[] =
69 /*! \class DATImageFileType
71 Image File Type to read/write and store/restore Image objects as
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",
83 sizeof(suffixArray
) );
86 DATImageFileType::KeyType
> DATImageFileType::_keyStrMap
;
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
;
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
;
114 Image::Type formatType
;
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;
126 formatType
= Image::OSG_INVALID_IMAGEDATATYPE
;
132 // read the data file
133 for(lineBuffer
[0] = 0;
134 inDat
.getline(lineBuffer
, lineBufferSize
);
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
))
148 valueL
= int(strlen(value
));
150 while (isspace(value
[valueL
-1]))
155 case OBJECT_FILE_NAME_KT
:
156 objectFileName
= value
;
157 image
->setAttachmentField ( keyStr
, value
);
160 sscanf ( value
, "%u", &(channel
) );
161 image
->setAttachmentField ( keyStr
, value
);
164 sscanf ( value
, "%u %u %u",
165 &(res
[0]), &(res
[1]), &(res
[2]));
166 image
->setAttachmentField ( keyStr
, value
);
169 formatI
= _formatStrMap
.find(value
);
170 if (formatI
!= _formatStrMap
.end())
172 formatType
= formatI
->second
.type
;
176 formatType
= Image::OSG_INVALID_IMAGEDATATYPE
;
178 image
->setAttachmentField ( keyStr
, value
);
181 if(!strcmp(value
, "LITTLE"))
183 image
->setAttachmentField ( keyStr
, value
);
186 sscanf ( value
, "%d", &fileOffset
);
187 image
->setAttachmentField ( keyStr
, value
);
190 FNOTICE (( "Uknown DAT file key: >%s<\n",
192 image
->setAttachmentField ( keyStr
, value
);
194 case SLICE_THICKNESS_KT
:
196 image
->setAttachmentField ( keyStr
, value
);
202 FINFO (("Skip DAT line\n"));
210 pixelFormat
= Image::OSG_RGBA_PF
;
213 pixelFormat
= Image::OSG_RGB_PF
;
216 pixelFormat
= Image::OSG_LA_PF
;
219 pixelFormat
= Image::OSG_L_PF
;
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
239 ImageFileHandler::the()->getPathHandler();
241 inVolS
.open(ph
->findFile(objectFileName
.c_str()).c_str(),
242 std::ios::in
| std::ios::binary
);
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
);
256 ImageFileHandler::the()->getPathHandler())
258 // Try to find the file in the search path
259 inVolS
.clear(); // reset the error state
262 ImageFileHandler::the()->getPathHandler();
264 inVolS
.open(ph
->findFile(gzname
.c_str()).c_str(),
265 std::ios::in
| std::ios::binary
);
272 zip_istream
*unzipper
= NULL
;
275 image
->set(pixelFormat
,
276 res
[0], res
[1], res
[2],
282 dataSize
= image
->getSize();
284 UInt32 fileDataSize
= dataSize
;
289 unzipper
= new zip_istream(inVolS
);
292 SFATAL
<< "Compressed streams are not supported! "
293 << "Configure with --enable-png "
294 << "--with-png=DIR options." << std::endl
;
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
)
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" ));
320 dataBuffer
= new char [ dataSize
];
325 reinterpret_cast<char *>(image
->editData());
329 inVol
->ignore (fileOffset
);
331 inVol
->read ( dataBuffer
, fileDataSize
);
340 FWARNING (( "Can not open %s image data\n",
341 objectFileName
.c_str() ));
346 FWARNING (( "Invalid/Missing DAT Format\n" ));
351 FWARNING (( "Invalid/Missing DAT Resolution\n" ));
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();
372 FLOG (("DAT-Data convert not impl. yet !\n"));
376 case Image::OSG_UINT8_IMAGEDATA
:
378 case Image::OSG_UINT16_IMAGEDATA
:
380 case Image::OSG_UINT32_IMAGEDATA
:
382 case Image::OSG_FLOAT32_IMAGEDATA
:
397 std::ifstream in(fileName);
399 void *headData = (void*)(&head);
400 unsigned dataSize, headSize = sizeof(Head);
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 ))
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
)
427 // ok we write always in big endian.
428 #if BYTE_ORDER == LITTLE_ENDIAN
429 Image
*pSwapImage
= const_cast<Image
*>(&(*image
));
431 pSwapImage
->swapDataEndian();
434 std::ofstream
dat(fileName
, std::ios::binary
);
438 SWARNING
<< "DATImageFileType::write : Can not open output stream "
448 sT
[0] = sT
[1] = sT
[2] = 1.0;
450 const std::string
*attr
= image
->findAttachmentField("SliceThickness");
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();
461 if((*it
).second
.type
== image
->getDataType())
463 format
= (*it
).first
;
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
);
476 std::string name
= basename
;
480 // on windows also a / is possible!
482 if(i
== std::string::npos
)
483 i
= name
.rfind("\\");
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";
505 std::ofstream
raw(basename
.c_str(), std::ios::binary
);
509 SWARNING
<< "DATImageFileType::write : Can not open output stream "
518 raw
.write (reinterpret_cast<const char *>(image
->getData()),
522 // restore to original endian
523 #if BYTE_ORDER == LITTLE_ENDIAN
524 pSwapImage
->swapDataEndian();
528 ofstream out(fileName);
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);
542 if ( out && out.write(static_cast<const char *>(headData), headSize) &&
544 out.write((char *)(image.getData()), dataSize) )
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
,
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
);
587 //-------------------------------------------------------------------------
588 /*! Constructor used for the singleton object
591 DATImageFileType::DATImageFileType(const Char8
*mimeType
,
592 const Char8
*suffixArray
[],
593 UInt16 suffixByteCount
) :
601 //-------------------------------------------------------------------------
605 DATImageFileType::~DATImageFileType(void)
609 //-------------------------------------------------------------------------
610 /*! Helper to initialize the type map;
613 void DATImageFileType::initTypeMap(void)
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
;
633 desc
->pixelFormat
= Image::OSG_L_PF
;
634 desc
->needConversion
= false;
636 desc
= &(_formatStrMap
["USHORT"]);
637 desc
->type
= Image::OSG_UINT16_IMAGEDATA
;
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
;
651 desc
->pixelFormat
= Image::OSG_L_PF
;
652 desc
->needConversion
= false;
654 desc
= &(_formatStrMap
["FLOAT"]);
655 desc
->type
= Image::OSG_FLOAT32_IMAGEDATA
;
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
;
664 desc
->pixelFormat
= Image::OSG_L_PF
;
665 desc
->needConversion
= false;