098d0c7272c585291cbe9998c148786f06c067ad
[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     const 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     void getDateString (string& str) const;
48 };
49
50
51 template<class T>
52 class Array2dFile 
53 {
54 private:
55   void init (void);
56   kuint16 signature;
57   kuint16 num_labels;
58   kuint16 headersize;
59   string  filename;
60   int file_id;
61   iostream *io;
62   bool bHeaderWritten;
63   bool bDataWritten;
64
65   bool headerWrite (void);
66
67   bool headerRead (void);
68
69   bool arrayDataRead (void);
70
71   bool labelSeek (unsigned int label_num);
72
73 public:
74   kuint16 pixel_size;
75   kuint16 pixel_type;
76   kuint32 nx;
77   kuint32 ny;
78
79   kuint16 axis_increment_known;
80   kfloat64 xinc, yinc;
81   kuint16 axis_extent_known;
82   kfloat64 xmin, xmax, ymin, ymax;
83   kfloat64 pv_offset, pv_scale;
84
85   Array2d<T> *array;
86
87   static const int INT8 = 1;
88   static const int UINT8 = 2;
89   static const int INT16 = 3;
90   static const int UINT16 = 4;
91   static const int INT32 = 5;
92   static const int UINT32 = 6;
93   static const int FLOAT32 = 7;
94   static const int FLOAT64 = 8;
95
96   Array2dFile (unsigned int nx, unsigned int ny);
97   Array2dFile (const char* const filename);
98   Array2dFile (const char* const filename, unsigned int nx, unsigned int ny);
99   ~Array2dFile ();
100
101   unsigned int getNumLabels (void) const
102       { return num_labels; }
103
104   bool labelRead (Array2dFileLabel& label, unsigned int label_num);
105
106   void labelAdd (const Array2dFileLabel& label);
107
108   void labelAdd (const char* const label_str, double calc_time=0.);
109
110   void labelAdd (int type, const char* const label_str, double calc_time=0.);
111
112   void fileClose (void);
113
114   void set_axis_increment (double xinc, double yinc);
115
116   void set_axis_extent (double xmin, double xmax, double ymin, double ymax);
117
118   void get_pixel_extent (T& pvmin, T& pvmax);
119       
120   void set_pixel_offset_extent (double offset, double scale);
121
122   T** getArray (void) const
123       { return (array == NULL ? NULL : array->getArray()); }
124
125   bool arrayDataWrite (void);
126
127   bool fileRead (void);
128
129   bool fileCreate (void);
130
131   const string& GetFilename (void) const 
132       {  return filename; }
133 };
134
135
136 template<class T>
137 void
138 Array2dFile<T>::set_axis_increment (double xinc, double yinc)
139 {
140     axis_increment_known = true;
141     this.xinc = xinc;
142     this.yinc = yinc;
143 }
144
145 template<class T>
146 void 
147 Array2dFile<T>::set_axis_extent (double xmin, double xmax, double ymin, double ymax)
148 {
149     axis_extent_known = true;
150     this.xmin = xmin;
151     this.ymax = xmax;
152     this.xmin = xmin;
153     this.ymax = ymax;
154 }
155
156 template<class T>
157 void 
158 Array2dFile<T>::get_pixel_extent (T& pvmin, T& pvmax)
159 {
160       if (array != NULL) {
161         T** da = array.GetArray();
162         pvmax = pvmin = da[0][0];
163           for (int ix = 0; ix < nx; ix++)
164               for (int iy = 0; iy < ny; iy++)
165                   if (pvmax < da[ix][iy])
166                       pvmax = da[ix][iy];
167                   else if (pvmin > da[ix][iy])
168                     pvmin = da[ix][iy];
169       }
170 }
171
172 template<class T>
173 void
174 Array2dFile<T>::set_pixel_offset_extent (double offset, double scale)
175 {
176       pv_offset = offset;
177       pv_scale = scale;
178 }
179
180 template<class T>
181 void
182 Array2dFile<T>::init (void)
183 {
184   pixel_size = sizeof(T);
185   signature = ('I' * 256 + 'F');
186   file_id = -1;
187   nx = 0;
188   ny = 0;
189   headersize = 0;
190   num_labels = 0;
191   axis_increment_known = false;
192   axis_extent_known = false;
193   xinc = ymin = 0;
194   xmin = xmax = ymin = ymax = 0;
195   pv_offset = 0;
196   pv_scale = 1;
197   array = NULL;
198   io = NULL;
199
200 #if 0
201   const type_info& t_id = typeid(T);
202   cout << t_id.name() << endl;
203   const type_info& comp_id = typeid(T);
204
205   if (t_id == comp_id)
206       pixel_type = FLOAT64;
207   else if (t_id == typeid(kfloat32))
208     pixel_type = FLOAT32;
209   else if (t_id == typeid(kint32))
210     pixel_type = INT32;
211   else if (t_id == typeid(kuint32))
212     pixel_type = UINT32;
213   else if (t_id == typeid(kint16))
214     pixel_type = INT16;
215   else if (t_id == typeid(kuint16))
216     pixel_type = UINT16;
217   else if (t_id == typeid(kint8))
218     pixel_type = INT8;
219   else if (t_id == typeid(kuint8))
220     pixel_type = UINT8;
221   else
222 #endif
223       pixel_type = 0;
224
225   bHeaderWritten = false;
226   bDataWritten = false;
227 }
228
229 template<class T>
230 Array2dFile<T>::Array2dFile (unsigned int x, unsigned int y)
231 {
232     init();
233     nx = x;
234     ny = y;
235     array = new Array2d<T> (nx, ny);
236 }
237
238 template<class T>
239 Array2dFile<T>::Array2dFile (const char * const str, unsigned int x, unsigned int y)
240   : filename(str)
241 {
242     init();
243     nx = x;
244     ny = y;
245     array = new Array2d<T> (nx, ny);
246 }
247
248 template<class T>
249 Array2dFile<T>::Array2dFile (const char * const str)
250   : filename(str)
251 {
252     init();
253 }
254
255 template<class T>
256 bool
257 Array2dFile<T>::fileCreate (void)
258 {
259   //  io = new iostream(filename, ios::out | ios::in | ios::trunc | io::binary);
260     if ((file_id = open (filename.c_str(), O_RDWR | O_CREAT | O_TRUNC | O_BINARY, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) < 0) {
261         sys_error (ERR_WARNING, "Error opening file %s for writing [fileCreate]", filename.c_str());
262         return (false);
263     }
264   headerWrite();
265   return (true);
266 }
267
268 template<class T>
269 bool
270 Array2dFile<T>::fileRead (void)
271 {
272   // io = new iostream(filename, ios::out | ios::in | io::binary);
273   if ((file_id = open (filename.c_str(), O_RDONLY | O_BINARY)) < 0) {
274     sys_error (ERR_WARNING, "Unable to open file %s [fileRead]", filename.c_str());
275     return (false);
276   }
277
278   headerRead();
279   if (array != NULL)
280     delete array;
281
282   array = new Array2d<T> (nx, ny);
283
284   arrayDataRead();
285
286   return (true);
287 }
288
289 template<class T>
290 bool
291 Array2dFile<T>::headerRead (void)
292 {
293   if (file_id < 0) {
294     sys_error (ERR_WARNING, "Tried to read header with file closed [headerRead]");
295     return (false);
296   }
297
298   lseek (file_id, 0, SEEK_SET);
299   kuint16 file_signature;
300   kuint16 file_pixel_size;
301   kuint16 file_pixel_type;
302
303   read_nint16 (&headersize, file_id);
304   read_nint16 (&file_signature, file_id);
305   read_nint16 (&num_labels, file_id);
306   read_nint16 (&file_pixel_type, file_id);
307   read_nint16 (&file_pixel_size, file_id);
308   read_nint32 (&nx, file_id);
309   read_nint32 (&ny, file_id);
310   read_nint16 (&axis_increment_known, file_id);
311   read_nfloat64 (&xinc, file_id);
312   read_nfloat64 (&yinc, file_id);
313   read_nint16 (&axis_extent_known, file_id);
314   read_nfloat64 (&xmin, file_id);
315   read_nfloat64 (&xmax, file_id);
316   read_nfloat64 (&ymin, file_id);
317   read_nfloat64 (&ymax, file_id);
318   read_nfloat64 (&pv_offset, file_id);
319   read_nfloat64 (&pv_scale, file_id);
320
321   int read_headersize = lseek (file_id, 0, SEEK_CUR);
322   if (read_headersize != headersize) {
323     sys_error (ERR_WARNING, "Read headersize %d != file headersize %d", read_headersize, headersize);
324     return (false);
325   }
326   if (file_signature != signature) {
327     sys_error (ERR_WARNING, "File signature %d != true signature %d", file_signature, signature);
328     return (false);
329   }
330   if (file_pixel_type != pixel_type) {
331     sys_error (ERR_WARNING, "File pixel type %d != class pixel type %d", file_pixel_type, pixel_type);
332     return (false);
333   }
334   if (file_pixel_size != pixel_size) {
335     sys_error (ERR_WARNING, "File pixel size %d != class pixel size %d", file_pixel_size, pixel_size);
336     return (false);
337   }
338
339   return (true);
340 }
341
342 template<class T>
343 bool
344 Array2dFile<T>::headerWrite (void)
345 {
346   if (file_id < 0) {
347     sys_error (ERR_WARNING, "Tried to write header with file closed");
348     return (false);
349   }
350
351   lseek (file_id, 0, SEEK_SET);
352   write_nint16 (&headersize, file_id);
353   write_nint16 (&signature, file_id);
354   write_nint16 (&num_labels, file_id);
355   write_nint16 (&pixel_type, file_id);
356   write_nint16 (&pixel_size, file_id);
357   write_nint32 (&nx, file_id);
358   write_nint32 (&ny, file_id);
359   write_nint16 (&axis_increment_known, file_id);
360   write_nfloat64 (&xinc, file_id);
361   write_nfloat64 (&yinc, file_id);
362   write_nint16 (&axis_extent_known, file_id);
363   write_nfloat64 (&xmin, file_id);
364   write_nfloat64 (&xmax, file_id);
365   write_nfloat64 (&ymin, file_id);
366   write_nfloat64 (&ymax, file_id);
367   write_nfloat64 (&pv_offset, file_id);
368   write_nfloat64 (&pv_scale, file_id);
369
370   headersize = lseek (file_id, 0, SEEK_CUR);
371   lseek (file_id, 0, SEEK_SET);
372   write_nint16 (&headersize, file_id);
373   
374   return (true);
375 }
376
377 template<class T>
378 bool
379 Array2dFile<T>::arrayDataWrite (void)
380 {
381   if (file_id < 0) {
382     sys_error (ERR_WARNING, "Tried to arrayDataWrite with file_id < 0");
383     return (false);
384   }
385
386   lseek (file_id, headersize, SEEK_SET);
387   for (unsigned int ix = 0; ix < nx; ix++)
388     {
389       write (file_id, array->array_data[ix], ny * pixel_size);
390     }
391
392   return (true);
393 }
394
395 template<class T>
396 void
397 Array2dFile<T>::fileClose (void)
398 {
399   headerWrite ();
400   if (file_id >= 0 && array != NULL) {
401     arrayDataWrite ();
402     close (file_id);
403     file_id = -1;
404   }
405 }
406
407 template<class T>
408 Array2dFile<T>::~Array2dFile (void)
409 {
410     fileClose ();
411 }
412
413
414 template<class T>
415 bool
416 Array2dFile<T>::arrayDataRead (void)
417 {
418   if (file_id < 0) {
419     sys_error (ERR_WARNING, "Tried to arrayDataRead with file_id < 0");
420     return (false);
421   }
422
423   lseek (file_id, headersize, SEEK_SET);
424   for (int ix = 0; ix < nx; ix++) 
425     {
426       read (file_id, array->array_data[ix], ny * pixel_size);
427     }
428
429   return (true);
430 }
431
432 template<class T>
433 bool
434 Array2dFile<T>::labelSeek (unsigned int label_num)
435 {
436   if (label_num > num_labels) {
437     sys_error (ERR_WARNING, "label_num %d > num_labels %d [labelSeek]");
438     return (false);
439   }
440
441   if (array == NULL) {    // Could not have written data if array not allocated
442     sys_error (ERR_WARNING, "array == NULL [labelSeek]");
443     return (false);
444   }
445
446   off_t pos = headersize + array->sizeofArray();
447   if (lseek (file_id, pos, SEEK_SET) != pos) {
448     sys_error (ERR_WARNING, "Can't seek to end of data array");
449     return (false);
450   }
451
452   for (int i = 0; i < label_num; i++)
453       {
454           pos += 22;  // Skip to string length
455           if (lseek (file_id, pos, SEEK_SET) != pos) {
456             sys_error (ERR_WARNING, "Can't seek to string length");
457             return (false);
458           }
459           kuint16 strlength;
460           read_nint16 (&strlength, file_id);
461           pos += 2 + strlength;  // Skip label string length + data
462           if (lseek (file_id, pos, SEEK_SET) != pos) {
463             sys_error (ERR_WARNING, "Can't seek past label string");
464             return (false);
465           }
466       }
467
468   return (true);
469 }
470
471 template<class T>
472 bool
473 Array2dFile<T>::labelRead (Array2dFileLabel& label, unsigned int label_num)
474 {
475   if (label_num >= num_labels) {
476     sys_error (ERR_WARNING, "Trying to read past number of labels [labelRead]");
477     return (false);
478   }
479
480   if (! labelSeek (label_num)) {
481     sys_error (ERR_WARNING, "Error calling labelSeek");
482     return (false);
483   }
484
485   read_nint16 (&label.label_type, file_id);
486   read_nint16 (&label.year, file_id);
487   read_nint16 (&label.month, file_id);
488   read_nint16 (&label.day, file_id);
489   read_nint16 (&label.hour, file_id);
490   read_nint16 (&label.minute, file_id);
491   read_nint16 (&label.second, file_id);
492   read_nfloat64 (&label.calc_time, file_id);
493
494   kuint16 strlength;
495   read_nint16 (&strlength, file_id);
496   char *str = new char [strlength+1];
497   read (file_id, str, strlength);
498   label.label_str = str;
499
500   return (true);
501 }
502
503
504 template<class T>
505 void
506 Array2dFile<T>::labelAdd (const char* const lstr, double calc_time=0.)
507 {
508   labelAdd (Array2dFileLabel::L_HISTORY, lstr, calc_time);
509 }
510
511 template<class T>
512 void
513 Array2dFile<T>::labelAdd (int type, const char* const lstr, double calc_time=0.)
514 {
515   Array2dFileLabel label (type, lstr, calc_time);
516
517   labelAdd (label);
518 }
519
520 template<class T>
521 void
522 Array2dFile<T>::labelAdd (const Array2dFileLabel& label)
523 {
524   labelSeek (num_labels);
525   
526   write_nint16 (&label.label_type, file_id);
527   write_nint16 (&label.year, file_id);
528   write_nint16 (&label.month, file_id);
529   write_nint16 (&label.day, file_id);
530   write_nint16 (&label.hour, file_id);
531   write_nint16 (&label.minute, file_id);
532   write_nint16 (&label.second, file_id);
533   write_nfloat64 (&label.calc_time, file_id);
534   kuint16 strlength = label.label_str.length();
535   write_nint16 (&strlength, file_id);
536   write (file_id, static_cast<const void*>(label.label_str.c_str()), strlength);
537
538   num_labels++;
539
540   headerWrite();
541   fsync(file_id);
542 }
543
544
545 #endif
546
547 #ifdef MPI_CT
548 #include <mpi.h>
549 #endif
550
551 class F32Image
552 {
553 public:
554   Array2dFile<kfloat32> adf;
555
556   F32Image (const char* const fname, unsigned int nx, unsigned int ny) : adf (fname, nx, ny)
557   {
558       adf.pixel_type = Array2dFile<kfloat32>::FLOAT32;
559   }
560
561   F32Image (unsigned int nx, unsigned int ny) : adf (nx, ny)
562   {
563       adf.pixel_type = Array2dFile<kfloat32>::FLOAT32;
564   }
565
566   F32Image (const char* const fname) : adf (fname)
567   {
568       adf.pixel_type = Array2dFile<kfloat32>::FLOAT32;
569   }
570
571 #ifdef MPI_CT
572   MPI_Datatype getMPIDataType (void) const
573       { return MPI_FLOAT; }
574 #endif
575 };
576
577 class F64Image 
578 {
579 public:
580   Array2dFile<kfloat64> adf;
581
582 #ifdef MPI_CT
583   MPI_Datatype getMPIDataType (void) const
584       { return MPI_DOUBLE; }
585 #endif
586
587   F64Image (const char* const fname, unsigned int nx, unsigned int ny) : adf (fname, nx, ny)
588   {
589       adf.pixel_type = Array2dFile<kfloat64>::FLOAT64;
590   }
591
592   F64Image (unsigned int nx, unsigned int ny) : adf (nx, ny)
593   {
594       adf.pixel_type = Array2dFile<kfloat64>::FLOAT64;
595   }
596
597   F64Image (const char* const fname) : adf (fname)
598   {
599       adf.pixel_type = Array2dFile<kfloat64>::FLOAT64;
600   }
601 };
602
603 typedef F64Image   ImageFile;
604 typedef kfloat64   ImageFileValue;
605 typedef kfloat64*  ImageFileColumn;
606 typedef kfloat64** ImageFileArray;
607
608
609