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