CtSaving_Edf.h 7.5 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//###########################################################################
// This file is part of LImA, a Library for Image Acquisition
//
// Copyright (C) : 2009-2011
// European Synchrotron Radiation Facility
// BP 220, Grenoble 38043
// FRANCE
//
// This is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 3 of the License, or
// (at your option) any later version.
//
// This software is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, see <http://www.gnu.org/licenses/>.
//###########################################################################
seb's avatar
seb committed
22
23
24
#ifndef CTSAVING_EDF_H
#define CTSAVING_EDF_H

25
#include "lima/CtSaving.h"
26
#include "lima/CtSaving_Compression.h"
seb's avatar
seb committed
27

28
29
#include <stack>

seb's avatar
seb committed
30
31
32
33
34
namespace lima {

  class SaveContainerEdf : public CtSaving::SaveContainer
  {
    DEB_CLASS_NAMESPC(DebModControl,"Saving EDF Container","Control");
35
36
    friend class FileZCompression;
    friend class FileLz4Compression;
seb's avatar
seb committed
37
  public:
38
39
40

    SaveContainerEdf(CtSaving::Stream& stream,
		     CtSaving::FileFormat format);
seb's avatar
seb committed
41
    virtual ~SaveContainerEdf();
42
43
    
    virtual bool needParallelCompression() const 
44
    {return m_format == CtSaving::EDFGZ || m_format == CtSaving::EDFLZ4;}
45
46
    virtual SinkTaskBase* getCompressionTask(const CtSaving::HeaderMap&);

seb's avatar
seb committed
47
  protected:
48
    virtual void* _open(const std::string &filename,
Alejandro Homs Puron's avatar
Alejandro Homs Puron committed
49
50
			std::ios_base::openmode flags,
			CtSaving::Parameters &pars);
51
    virtual void _close(void*);
52
    virtual long _writeFile(void*,Data &data,
seb's avatar
seb committed
53
54
			    CtSaving::HeaderMap &aHeader,
			    CtSaving::FileFormat);
Alejandro Homs Puron's avatar
Alejandro Homs Puron committed
55
56
    virtual void _prepare(CtControl&);

57
58
  private:
    struct MmapInfo
59
60
61
62
63
64
    {
      MmapInfo() :
	header_size(0),
	height_offset(0),
	size_offset(0),
	mmap_addr(NULL) {}
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81

#ifdef __unix
      ~MmapInfo();

      void map(const std::string& fname,
	       long long header_position);

      operator bool()
      { return mmap_addr; }

      char *sizeLocation()
      { return (char*) mmap_addr + size_offset; }

      char *heightLocation()
      { return (char*) mmap_addr + height_offset; }
#endif

82
83
84
85
86
      long long header_size;
      long long height_offset;
      long long size_offset;
      void* mmap_addr;
    };
87
    template<class Stream>
Alejandro Homs Puron's avatar
Alejandro Homs Puron committed
88
89
    MmapInfo _writeEdfHeader(Data&,CtSaving::HeaderMap&,
			     Stream&,int nbCharReserved = 0);
90

91
92
93
94
95
96
#ifdef WIN32
    class _OfStream
    {
    public:
      _OfStream();
      ~_OfStream();
seb's avatar
seb committed
97

98
99
100
101
102
103
104
      void clear();
      void exceptions(int exc);
      void open(const char* filename,
		std::ios_base::openmode openFlags = 
		std::ios_base::in | std::ios_base::out);
      bool is_open() const;
      void close();
105
      _int64 tellp() const;
Sebastien Petitdemange's avatar
Sebastien Petitdemange committed
106
      inline _OfStream& write(const char* data,size_t size);
107
108
109
110
111
112
113
114
      inline _OfStream& operator<< (const char *data);
      inline _OfStream& operator<< (const std::string& data);
      inline _OfStream& operator<< (const int data);
      inline _OfStream& operator<< (const long data);
    private:
      FILE* m_fout;
      int m_exc_flag;
    };
115
116
117
118
119
120
#endif

    struct File
    {
#ifdef WIN32
      typedef _OfStream Stream;
121
#else
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
      typedef std::ofstream Stream;
#endif

      File(SaveContainerEdf& cont, const std::string& filename,
	   std::ios_base::openmode openFlags);
      virtual ~File();

      SaveContainerEdf&		 m_cont;
      std::string		 m_filename;
      Stream			 m_fout;

#ifdef __unix
      void*			 m_buffer;
      MmapInfo			 m_mmap_info;
      long long			 m_height;
      long long			 m_size;
138
#endif
139
140
141
142
143
144
145
146
147
148
    };

#ifdef __unix
    void *getNewBuffer();
    void releaseBuffer(void *buffer);

    std::stack<void*>		 m_free_buffers;
    int				 m_nb_buffers;
#endif

149
    CtSaving::FileFormat	 m_format;
Alejandro Homs Puron's avatar
Alejandro Homs Puron committed
150
    long			 m_frames_per_file;
seb's avatar
seb committed
151
152
  };

153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
  template<class Stream>
    SaveContainerEdf::MmapInfo
    SaveContainerEdf::_writeEdfHeader(Data &aData,
				      CtSaving::HeaderMap &aHeader,
				      Stream &sout,
				      int nbCharReserved)
    {
      time_t ctime_now;
      time(&ctime_now);
      
      struct timeval tod_now;
      gettimeofday(&tod_now, NULL);
      
      char time_str[64];
      ctime_r(&ctime_now, time_str);
      time_str[strlen(time_str) - 1] = '\0';
      
Alejandro Homs Puron's avatar
Alejandro Homs Puron committed
170
      int image_nb = aData.frameNumber % m_frames_per_file;
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
      
      char aBuffer[2048];
      long long aStartPosition = sout.tellp();
      sout << "{\n";
      
      snprintf(aBuffer,sizeof(aBuffer),"HeaderID = EH:%06u:000000:000000 ;\n", image_nb + 1);
      sout << aBuffer;
      
      sout << "ByteOrder = LowByteFirst ;\n";
      const char *aStringType = NULL;
      switch(aData.type)
	{
	case Data::UINT8:	aStringType = "UnsignedByte";break;
	case Data::INT8:	aStringType = "SignedByte";break;
	case Data::UINT16:	aStringType = "UnsignedShort";break;
	case Data::INT16:	aStringType = "SignedShort";break;
	case Data::UINT32:	aStringType = "UnsignedInteger";break;
	case Data::INT32:	aStringType = "SignedInteger";break;
	case Data::UINT64:	aStringType = "Unsigned64";break;
	case Data::INT64:	aStringType = "Signed64";break;
	case Data::FLOAT:	aStringType = "FloatValue";break;
	case Data::DOUBLE:	aStringType = "DoubleValue";break;
	default:
	  break;		// @todo ERROR has to be manage
	}
      sout << "DataType = " << aStringType << " ;\n";
      
198
199
      SaveContainerEdf::MmapInfo mmap_info;
      sout << "Size = "; mmap_info.size_offset = sout.tellp();
200
201
202
203
204
      snprintf(aBuffer,sizeof(aBuffer),"%*s ;\n",nbCharReserved,"");
      sout << aData.size() << aBuffer;
      
      sout << "Dim_1 = " << aData.dimensions[0] << " ;\n";
      
205
      sout << "Dim_2 = "; mmap_info.height_offset = sout.tellp();
206
      snprintf(aBuffer,sizeof(aBuffer),"%*s ;\n",nbCharReserved,"");
207
208
209
210
      int rows = aData.dimensions[1];
      if (aData.dimensions.size() == 3)
	rows *= aData.dimensions[2];
      sout << rows << aBuffer;
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
      
      sout << "Image = " << image_nb << " ;\n";
      
      sout << "acq_frame_nb = " << aData.frameNumber << " ;\n";
      sout << "time = " << time_str << " ;\n";
      
      snprintf(aBuffer,sizeof(aBuffer),"time_of_day = %ld.%06ld ;\n",tod_now.tv_sec, tod_now.tv_usec);
      sout << aBuffer;
      
      snprintf(aBuffer,sizeof(aBuffer),"time_of_frame = %.6f ;\n",aData.timestamp);
      sout << aBuffer;
      
      //@todo sout << "valid_pixels = " << aData.validPixels << " ;\n";
      
      
      aData.header.lock();
      Data::HeaderContainer::Header &aDataHeader = aData.header.header();
      for(Data::HeaderContainer::Header::iterator i = aDataHeader.begin();i != aDataHeader.end();++i)
	{
	  if(!i->second.size())
	    sout << i->first << " = " << ";\n";
	  else
	    sout << i->first << " = " << i->second << " ;\n";
	}
      aData.header.unlock();
      
      for(CtSaving::HeaderMap::iterator i = aHeader.begin(); i != aHeader.end();++i)
	{
	  if(!i->second.size())
	    sout << i->first << " = " << ";\n";
	  else
	    sout << i->first << " = " << i->second << " ;\n";
	}
      
      
      long long aEndPosition = sout.tellp();
      
      long long lenght = aEndPosition - aStartPosition + 2;
      long long finalHeaderLenght = (lenght + 1023) & ~1023; // 1024 alignment
      snprintf(aBuffer,sizeof(aBuffer),"%*s}\n",int(finalHeaderLenght - lenght),"");
      sout << aBuffer;
252
253
      mmap_info.header_size = finalHeaderLenght;
      return mmap_info;
254
255
    }

seb's avatar
seb committed
256
257
}
#endif // CTSAVING_EDF_H