r118: *** empty log message ***
[ctsim.git] / include / imagefile.h
1 #ifndef IDF_H
2 #define IDF_H
3
4 #include <string>
5 #include <sys/types.h>
6 #include <unistd.h>
7 #include <fstream>
8 #include <iostream>
9 #include "ctsupport.h"
10 #include "fnetorderstream.h"
11 #include "array2d.h"
12
13 using namespace std;
14
15
16 class Array2dFileLabel
17 {
18 private:
19     void init (void);
20     Array2dFileLabel (const Array2dFileLabel&);
21     Array2dFileLabel& operator= (const Array2dFileLabel&);
22
23 public:
24     kfloat64 m_calcTime;
25     kuint16 m_labelType;
26     kuint16 m_year;
27     kuint16 m_month;
28     kuint16 m_day;
29     kuint16 m_hour;
30     kuint16 m_minute;
31     kuint16 m_second;
32     string m_strLabel;
33     mutable string m_strDate;
34
35     static const int L_EMPTY = 0;
36     static const int L_HISTORY = 1;
37     static const int L_USER = 2;
38
39     Array2dFileLabel(); 
40
41     Array2dFileLabel(const char* const str, double ctime = 0.);
42
43     Array2dFileLabel(const int type, const char* const str, double ctime = 0.);
44
45     ~Array2dFileLabel();
46
47     const string& getLabelString (void) const
48         { return m_strLabel; }
49
50     kfloat64 getCalcTime (void) const
51         { return m_calcTime; }
52
53     kfloat64 getLabelType (void) const
54         { return m_labelType; }
55
56     string& setLabelString (const char* const str)
57         { m_strLabel = str; return (m_strLabel); }
58
59     string& setLabelString (const string& str)
60         { m_strLabel = str; return (m_strLabel); }
61
62     const string& getDateString () const;
63 };
64
65
66 template<class T>
67 class Array2dFile 
68 {
69 private:
70   void init (void);
71   kuint16 signature;
72   kuint16 num_labels;
73   kuint16 headersize;
74   string  filename;
75   int file_id;
76   frnetorderstream *m_pFS;
77   bool bHeaderWritten;
78   bool bDataWritten;
79
80   bool headerWrite (void);
81
82   bool headerRead (void);
83
84   bool arrayDataRead (void);
85
86   bool labelSeek (unsigned int label_num);
87
88   kuint16 mPixelSize;
89   kuint16 axis_increment_known;
90   kfloat64 mIncX, mIncY;
91   kuint16 axis_extent_known;
92   kfloat64 mMinX, mMaxX, mMinY, mMaxY;
93   kfloat64 mOffsetPV, mScalePV;
94   kuint16 mPixelType;
95   kuint32 mNX;
96   kuint32 mNY;
97
98   Array2dFile (const Array2dFile&);
99   Array2dFile& operator= (const Array2dFile&);
100
101 public:
102
103   Array2d<T> array;
104
105   static const int INT8 = 1;
106   static const int UINT8 = 2;
107   static const int INT16 = 3;
108   static const int UINT16 = 4;
109   static const int INT32 = 5;
110   static const int UINT32 = 6;
111   static const int FLOAT32 = 7;
112   static const int FLOAT64 = 8;
113
114   Array2dFile (unsigned int nx, unsigned int ny);
115   Array2dFile (const char* const filename);
116   Array2dFile (const char* const filename, unsigned int nx, unsigned int ny);
117   ~Array2dFile ();
118
119   unsigned int getNumLabels (void) const
120       { return num_labels; }
121
122   bool labelRead (Array2dFileLabel& label, unsigned int label_num);
123
124   void labelAdd (const Array2dFileLabel& label);
125
126   void labelAdd (const char* const m_strLabel, double calc_time=0.);
127
128   void labelAdd (int type, const char* const m_strLabel, double calc_time=0.);
129
130   void labelsCopy (Array2dFile& file, const char* const idStr = NULL);
131
132   void fileClose (void);
133
134   void setPixelType (int type)
135       { mPixelType = type; }
136
137   kuint32 nx (void) const
138       { return mNX; }
139
140   kuint32 ny (void) const
141       { return mNY; }
142
143   void setAxisIncrement (double mIncX, double mIncY);
144
145   void setAxisExtent (double mMinX, double mMaxX, double mMinY, double mMaxY);
146
147   void getPixelValueRange (T& pvmin, T& pvmax) const;
148       
149   void doPixelOffsetScale (double offset, double scale);
150
151   T** getArray (void) const
152       { return (array.getArray()); }
153
154   bool arrayDataWrite (void);
155
156   void arrayDataClear (void);
157
158   bool fileRead (void);
159
160   bool fileCreate (void);
161
162   const string& GetFilename (void) const 
163       {  return filename; }
164 };
165
166
167 template<class T>
168 Array2dFile<T>::Array2dFile (unsigned int x, unsigned int y)
169 {
170     init();
171     mNX = x;
172     mNY = y;
173     array.initSetSize(mNX, mNY);
174 }
175
176 template<class T>
177 Array2dFile<T>::Array2dFile (const char * const str, unsigned int x, unsigned int y)
178   : filename(str)
179 {
180     init();
181     mNX = x;
182     mNY = y;
183     array.initSetSize(mNX, mNY);
184 }
185
186 template<class T>
187 Array2dFile<T>::Array2dFile (const char * const str)
188   : filename(str)
189 {
190     init();
191 }
192
193 template<class T>
194 void
195 Array2dFile<T>::init (void)
196 {
197   mPixelSize = sizeof(T);
198   signature = ('I' * 256 + 'F');
199   mNX = 0;
200   mNY = 0;
201   headersize = 0;
202   num_labels = 0;
203   axis_increment_known = false;
204   axis_extent_known = false;
205   mIncX = mMinY = 0;
206   mMinX = mMaxX = mMinY = mMaxY = 0;
207   mOffsetPV = 0;
208   mScalePV = 1;
209   m_pFS = NULL;
210
211 #if 0
212   const type_info& t_id = typeid(T);
213   cout << t_id.name() << endl;
214   const type_info& comp_id = typeid(T);
215
216   if (t_id == comp_id)
217       mPixelType = FLOAT64;
218   else if (t_id == typeid(kfloat32))
219     mPixelType = FLOAT32;
220   else if (t_id == typeid(kint32))
221     mPixelType = INT32;
222   else if (t_id == typeid(kuint32))
223     mPixelType = UINT32;
224   else if (t_id == typeid(kint16))
225     mPixelType = INT16;
226   else if (t_id == typeid(kuint16))
227     mPixelType = UINT16;
228   else if (t_id == typeid(kint8))
229     mPixelType = INT8;
230   else if (t_id == typeid(kuint8))
231     mPixelType = UINT8;
232   else
233 #endif
234       mPixelType = 0;
235
236   bHeaderWritten = false;
237   bDataWritten = false;
238 }
239
240 template<class T>
241 Array2dFile<T>::~Array2dFile (void)
242 {
243     fileClose ();
244 }
245
246
247 template<class T>
248 void
249 Array2dFile<T>::fileClose (void)
250 {
251   if (m_pFS) {
252       headerWrite ();
253       m_pFS->close ();
254       m_pFS = NULL;
255   }
256 }
257
258 template<class T>
259 bool
260 Array2dFile<T>::fileCreate (void)
261 {
262   m_pFS = new frnetorderstream (filename.c_str(), ios::out | ios::in | ios::trunc | ios::binary);
263   if (! m_pFS) {
264       sys_error (ERR_WARNING, "Error opening file %s for writing [fileCreate]", filename.c_str());
265       return (false);
266   }
267   headerWrite();
268   return (true);
269 }
270
271 template<class T>
272 bool
273 Array2dFile<T>::fileRead (void)
274 {
275   m_pFS = new frnetorderstream (filename.c_str(), ios::out | ios::in | ios::binary | ios::nocreate);
276   if (m_pFS->fail()) {
277     sys_error (ERR_WARNING, "Unable to open file %s [fileRead]", filename.c_str());
278     return (false);
279   }
280
281   if (! headerRead())
282       return false;
283
284   array.initSetSize(mNX, mNY);
285
286   arrayDataRead();
287
288   return (true);
289 }
290
291 template<class T>
292 void
293 Array2dFile<T>::setAxisIncrement (double incX, double incY)
294 {
295     axis_increment_known = true;
296     mIncX = incX;
297     mIncY = incY;
298 }
299
300 template<class T>
301 void 
302 Array2dFile<T>::setAxisExtent (double minX, double maxX, double minY, double maxY)
303 {
304     axis_extent_known = true;
305     mMinX = minX;
306     mMaxY = maxX;
307     mMinX = minX;
308     mMaxY = maxY;
309 }
310
311 template<class T>
312 void 
313 Array2dFile<T>::getPixelValueRange (T& pvmin, T& pvmax) const
314 {
315     T** da = array.getArray();
316     if (da) {
317         pvmax = pvmin = da[0][0];
318         for (int ix = 0; ix < mNX; ix++)
319             for (int iy = 0; iy < mNY; iy++)
320                 if (pvmax < da[ix][iy])
321                     pvmax = da[ix][iy];
322                 else if (pvmin > da[ix][iy])
323                     pvmin = da[ix][iy];
324     }
325 }
326
327 template<class T>
328 void
329 Array2dFile<T>::doPixelOffsetScale (double offset, double scale)
330 {
331     T** ad = array.getArray();
332     if (ad) {
333         mOffsetPV = offset;
334         mScalePV = scale;
335
336         for (unsigned int ix = 0; ix < mNX; ix++) 
337             for (unsigned int iy = 0; iy < mNY; iy++)
338                 ad[ix][iy] = (ad[ix][iy] - offset) * scale;
339     }
340 }
341
342 template<class T>
343 bool
344 Array2dFile<T>::headerRead (void)
345 {
346   if (! m_pFS) {
347     sys_error (ERR_WARNING, "Tried to read header with file closed [headerRead]");
348     return (false);
349   }
350
351   m_pFS->seekg (0);
352   kuint16 file_signature;
353   kuint16 file_mPixelSize;
354   kuint16 file_mPixelType;
355
356   m_pFS->readInt16 (headersize);
357   m_pFS->readInt16 (file_signature);
358   m_pFS->readInt16 (num_labels);
359   m_pFS->readInt16 (file_mPixelType);
360   m_pFS->readInt16 (file_mPixelSize);
361   m_pFS->readInt32 (mNX);
362   m_pFS->readInt32 (mNY);
363   m_pFS->readInt16 (axis_increment_known);
364   m_pFS->readFloat64 (mIncX);
365   m_pFS->readFloat64 (mIncY);
366   m_pFS->readInt16 (axis_extent_known);
367   m_pFS->readFloat64 (mMinX);
368   m_pFS->readFloat64 (mMaxX);
369   m_pFS->readFloat64 (mMinY);
370   m_pFS->readFloat64 (mMaxY);
371   m_pFS->readFloat64 (mOffsetPV);
372   m_pFS->readFloat64 (mScalePV);
373
374   int read_headersize = m_pFS->tellg();
375   if (read_headersize != headersize) {
376     sys_error (ERR_WARNING, "Read headersize %d != file headersize %d", read_headersize, headersize);
377     return (false);
378   }
379   if (file_signature != signature) {
380     sys_error (ERR_WARNING, "File signature %d != true signature %d", file_signature, signature);
381     return (false);
382   }
383   if (file_mPixelType != mPixelType) {
384     sys_error (ERR_WARNING, "File pixel type %d != class pixel type %d", file_mPixelType, mPixelType);
385     return (false);
386   }
387   if (file_mPixelSize != mPixelSize) {
388     sys_error (ERR_WARNING, "File pixel size %d != class pixel size %d", file_mPixelSize, mPixelSize);
389     return (false);
390   }
391
392   return (true);
393 }
394
395 template<class T>
396 bool
397 Array2dFile<T>::headerWrite (void)
398 {
399   if (! m_pFS) {
400     sys_error (ERR_WARNING, "Tried to write header with file closed");
401     return (false);
402   }
403
404   m_pFS->seekp (0);
405   m_pFS->writeInt16 (headersize);
406   m_pFS->writeInt16 (signature);
407   m_pFS->writeInt16 (num_labels);
408   m_pFS->writeInt16 (mPixelType);
409   m_pFS->writeInt16 (mPixelSize);
410   m_pFS->writeInt32 (mNX);
411   m_pFS->writeInt32 (mNY);
412   m_pFS->writeInt16 (axis_increment_known);
413   m_pFS->writeFloat64 (mIncX);
414   m_pFS->writeFloat64 (mIncY);
415   m_pFS->writeInt16 (axis_extent_known);
416   m_pFS->writeFloat64 (mMinX);
417   m_pFS->writeFloat64 (mMaxX);
418   m_pFS->writeFloat64 (mMinY);
419   m_pFS->writeFloat64 (mMaxY);
420   m_pFS->writeFloat64 (mOffsetPV);
421   m_pFS->writeFloat64 (mScalePV);
422
423   headersize = m_pFS->tellp();
424   m_pFS->writeInt16 (headersize);
425   
426   return (true);
427 }
428
429 template<class T>
430 bool
431 Array2dFile<T>::arrayDataWrite (void)
432 {
433   if (! m_pFS) {
434     sys_error (ERR_WARNING, "Tried to arrayDataWrite with !m_pFS");
435     return (false);
436   }
437
438   T** da = array.getArray();
439   if (! da) 
440       return (false);
441
442   m_pFS->seekp (headersize);
443   for (unsigned int ix = 0; ix < mNX; ix++) {
444       if (NativeBigEndian()) {
445           for (unsigned int iy = 0; iy < mNY; iy++) {
446               T value = da[ix][iy];
447               ConvertReverseNetworkOrder (&value, sizeof(T));
448               m_pFS->write (&value, mPixelSize);
449           }
450       } else 
451           m_pFS->write (da[ix], sizeof(T) * mNY);
452   }
453
454   return (true);
455 }
456
457 template<class T>
458 bool
459 Array2dFile<T>::arrayDataRead (void)
460 {
461   if (! m_pFS) {
462     sys_error (ERR_WARNING, "Tried to arrayDataRead with !m_pFS");
463     return (false);
464   }
465
466   T** da = array.getArray();
467   if (! da) 
468       return (false);
469
470   m_pFS->seekg (headersize);
471   T pixelBuffer;
472   for (int ix = 0; ix < mNX; ix++) {
473       if (NativeBigEndian()) {
474           for (unsigned int iy = 0; iy < mNY; iy++) {
475               m_pFS->read (&pixelBuffer, mPixelSize);
476               ConvertReverseNetworkOrder (&pixelBuffer, sizeof(T));
477               da[ix][iy] = pixelBuffer;
478           } 
479       } else
480           m_pFS->read (da[ix], sizeof(T) * mNY);
481   }
482
483
484   return (true);
485 }
486
487 template<class T>
488 bool
489 Array2dFile<T>::labelSeek (unsigned int label_num)
490 {
491   if (label_num > num_labels) {
492     sys_error (ERR_WARNING, "label_num %d > num_labels %d [labelSeek]");
493     return (false);
494   }
495
496   if (array.getArray() == NULL) {    // Could not have written data if array not allocated
497     sys_error (ERR_WARNING, "array == NULL [labelSeek]");
498     return (false);
499   }
500
501   off_t pos = headersize + array.sizeofArray();
502   m_pFS->seekg (pos);
503
504   for (int i = 0; i < label_num; i++)
505       {
506           pos += 22;  // Skip to string length
507           m_pFS->seekg (pos);
508               
509           kuint16 strlength;
510           m_pFS->readInt16 (strlength);
511           pos += 2 + strlength;  // Skip label string length + data
512           m_pFS->seekg (pos);
513       }
514   
515   if (! m_pFS)
516       return false;
517
518   return (true);
519 }
520
521 template<class T>
522 bool
523 Array2dFile<T>::labelRead (Array2dFileLabel& label, unsigned int label_num)
524 {
525   if (label_num >= num_labels) {
526     sys_error (ERR_WARNING, "Trying to read past number of labels [labelRead]");
527     return (false);
528   }
529
530   if (! labelSeek (label_num)) {
531     sys_error (ERR_WARNING, "Error calling labelSeek");
532     return (false);
533   }
534
535   m_pFS->readInt16 (label.m_labelType);
536   m_pFS->readInt16 (label.m_year);
537   m_pFS->readInt16 (label.m_month);
538   m_pFS->readInt16 (label.m_day);
539   m_pFS->readInt16 (label.m_hour);
540   m_pFS->readInt16 (label.m_minute);
541   m_pFS->readInt16 (label.m_second);
542   m_pFS->readFloat64 (label.m_calcTime);
543
544   kuint16 strlength;
545   m_pFS->readInt16 (strlength);
546   char str [strlength+1];
547   m_pFS->read (str, strlength);
548   str[strlength] = 0;
549   label.m_strLabel = str;
550
551   return (true);
552 }
553
554
555 template<class T>
556 void
557 Array2dFile<T>::labelAdd (const char* const lstr, double calc_time=0.)
558 {
559   labelAdd (Array2dFileLabel::L_HISTORY, lstr, calc_time);
560 }
561
562 template<class T>
563 void
564 Array2dFile<T>::labelAdd (int type, const char* const lstr, double calc_time=0.)
565 {
566   Array2dFileLabel label (type, lstr, calc_time);
567
568   labelAdd (label);
569 }
570
571 template<class T>
572 void
573 Array2dFile<T>::labelAdd (const Array2dFileLabel& label)
574 {
575   labelSeek (num_labels);
576   
577   m_pFS->writeInt16 (label.m_labelType);
578   m_pFS->writeInt16 (label.m_year);
579   m_pFS->writeInt16 (label.m_month);
580   m_pFS->writeInt16 (label.m_day);
581   m_pFS->writeInt16 (label.m_hour);
582   m_pFS->writeInt16 (label.m_minute);
583   m_pFS->writeInt16 (label.m_second);
584   m_pFS->writeFloat64 (label.m_calcTime);
585   kuint16 strlength = label.m_strLabel.length();
586   m_pFS->writeInt16 (strlength);
587   m_pFS->write (label.m_strLabel.c_str(), strlength);
588
589   num_labels++;
590
591   headerWrite();
592 }
593
594 template<class T>
595 void
596 Array2dFile<T>::labelsCopy (Array2dFile& copyFile, const char* const idStr)
597 {
598     string id = idStr;
599     for (int i = 0; i < copyFile.getNumLabels(); i++) {
600       Array2dFileLabel l;
601       copyFile.labelRead (l, i);
602       string lstr = l.getLabelString();
603       lstr = idStr + lstr;
604       l.setLabelString (lstr);
605       labelAdd (l);
606     }
607 }
608
609 template<class T>
610 void 
611 Array2dFile<T>::arrayDataClear (void)
612 {
613     T** v = array.getArray();
614     if (v) {
615         for (unsigned int ix = 0; ix < mNX; ix++)
616             for (unsigned int iy = 0; iy < mNY; iy++)
617                 v[ix][iy] = 0;
618     }
619 }
620
621
622 #ifdef HAVE_MPI
623 #include <mpi++.h>
624 #endif
625
626 class F32Image : public Array2dFile<kfloat32>
627 {
628 public:
629   F32Image (const char* const fname, unsigned int nx, unsigned int ny)
630       : Array2dFile<kfloat32>::Array2dFile (fname, nx, ny)
631   {
632       setPixelType (FLOAT32);
633   }
634
635   F32Image (unsigned int nx, unsigned int ny)
636       : Array2dFile<kfloat32>::Array2dFile (nx, ny)
637   {
638       setPixelType (FLOAT32);
639   }
640
641   F32Image (const char* const fname)
642       : Array2dFile<kfloat32>::Array2dFile (fname)
643   {
644       setPixelType (FLOAT32);
645   }
646
647 #ifdef HAVE_MPI
648   MPI::Datatype getMPIDataType (void) const
649       { return MPI::FLOAT; }
650 #endif
651 };
652
653
654 class F64Image : public Array2dFile<kfloat64>
655 {
656  public:
657
658   F64Image (const char* const fname, unsigned int nx, unsigned int ny)
659       : Array2dFile<kfloat64>::Array2dFile (fname, nx, ny)
660   {
661       setPixelType (FLOAT64);
662   }
663
664   F64Image (unsigned int nx, unsigned int ny)
665       : Array2dFile<kfloat64>::Array2dFile (nx, ny)
666   {
667       setPixelType (FLOAT64);
668   }
669
670   F64Image (const char* const fname)
671       : Array2dFile<kfloat64>::Array2dFile (fname)
672   {
673       setPixelType (FLOAT64);
674   }
675
676 #ifdef HAVE_MPI
677   MPI::Datatype getMPIDataType (void) const
678       { return MPI::DOUBLE; }
679 #endif
680 };
681
682 #undef IMAGEFILE_64_BITS
683 #ifdef IMAGEFILE_64_BITS
684 typedef F64Image   ImageFile;
685 typedef kfloat64   ImageFileValue;
686 typedef kfloat64*  ImageFileColumn;
687 typedef kfloat64** ImageFileArray;
688 #else
689 typedef F32Image   ImageFile;
690 typedef kfloat32   ImageFileValue;
691 typedef kfloat32*  ImageFileColumn;
692 typedef kfloat32** ImageFileArray;
693 #endif
694
695
696 // imagefile.cpp 
697 void image_filter_response (ImageFile& im, const char* const domainName, double bw, const char* const filterName, double filt_param, const int opt_trace);
698 int image_display (const ImageFile& im);
699 int image_display_scale (const ImageFile& im, const int scale, const double pmin, const double pmax);
700
701
702 #endif
703
704
705