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