bes  Updated for version 3.20.6
gri.cc
1 // This file is part of the hdf4 data handler for the OPeNDAP data server.
2 
3 // Copyright (c) 2005 OPeNDAP, Inc.
4 // Author: James Gallagher <jgallagher@opendap.org>
5 //
6 // This is free software; you can redistribute it and/or modify it under the
7 // terms of the GNU Lesser General Public License as published by the Free
8 // Software Foundation; either version 2.1 of the License, or (at your
9 // option) any later version.
10 //
11 // This software is distributed in the hope that it will be useful, but
12 // WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 // or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
14 // License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public License
17 // along with this software; if not, write to the Free Software Foundation,
18 // Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 //
20 // You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
21 
23 // Copyright 1996, by the California Institute of Technology.
24 // ALL RIGHTS RESERVED. United States Government Sponsorship
25 // acknowledged. Any commercial use must be negotiated with the
26 // Office of Technology Transfer at the California Institute of
27 // Technology. This software may be subject to U.S. export control
28 // laws and regulations. By accepting this software, the user
29 // agrees to comply with all applicable U.S. export laws and
30 // regulations. User has the responsibility to obtain export
31 // licenses, or other export authority as may be required before
32 // exporting such information to foreign countries or providing
33 // access to foreign persons.
34 
35 // U.S. Government Sponsorship under NASA Contract
36 // NAS7-1260 is acknowledged.
37 //
38 // Author: Isaac.C.Henry@jpl.nasa.gov
39 //
40 // $RCSfile: gri.cc,v $ - input stream class for HDF GR
41 //
43 
44 #include "config_hdf.h"
45 
46 #include <mfhdf.h>
47 #include <mfgr.h>
48 
49 #ifdef __POWERPC__
50 #undef isascii
51 #endif
52 
53 #include <string>
54 #include <vector>
55 
56 #include <hcstream.h>
57 #include <hdfclass.h>
58 #include <hcerr.h>
59 
60 // minimum function
61 inline int min(int t1, int t2)
62 {
63  return (t1 < t2 ? t1 : t2);
64 }
65 
66 // initialize a hdfistream_gri
67 void hdfistream_gri::_init(void)
68 {
69  _ri_id = _attr_index = _pal_index = 0;
70  _npals = _nri = _nattrs = _nfattrs = _gr_id = _file_id = 0;
71  _index = _interlace_mode = -1;
72  _meta = _slab.set = false;
73  return;
74 }
75 
76 // retrieve descriptive information about the file containing RI
77 void hdfistream_gri::_get_fileinfo(void)
78 {
79  if (GRfileinfo(_gr_id, &_nri, &_nfattrs) < 0)
80  THROW(hcerr_griinfo);
81  return;
82 }
83 
84 // retrieve information about open raster image
85 void hdfistream_gri::_get_iminfo(void)
86 {
87  char junk0[hdfclass::MAXSTR];
88  int32 junk1, junk2, junk3, junk4[2];
89  if (GRgetiminfo(_ri_id, junk0, &junk1, &junk2, &junk3, junk4, &_nattrs)
90  < 0)
91  THROW(hcerr_griinfo);
92  else { // find out how many palettes are associated with the image
93  GRgetlutinfo(GRgetlutid(_ri_id, 0), &junk1, &junk2, &junk3,
94  &junk1);
95  if (junk2 == 0)
96  _npals = 0;
97  else
98  _npals = 1;
99  }
100  return;
101 }
102 
103 // end access to open raster image
104 void hdfistream_gri::_close_ri(void)
105 {
106  if (_ri_id != 0) {
107  GRendaccess(_ri_id);
108  _ri_id = _attr_index = _pal_index = _nattrs = 0;
109  _index = -1;
110  }
111  return;
112 }
113 
114 // constructor
115 hdfistream_gri::hdfistream_gri(const string filename):hdfistream_obj
116  (filename)
117 {
118  _init();
119  if (_filename.length() != 0)
120  open(_filename.c_str());
121  return;
122 }
123 
124 // open the GRI input stream
125 void hdfistream_gri::open(const char *filename)
126 {
127  if (filename == 0) // no filename given
128  THROW(hcerr_openfile);
129  if (_file_id != 0) // close any currently open file
130  close();
131  if ((_file_id = Hopen((char *) filename, DFACC_RDONLY, 0)) < 0)
132  THROW(hcerr_openfile);
133  _filename = filename; // assign filename
134  if ((_gr_id = GRstart(_file_id)) < 0)
135  THROW(hcerr_openfile);
136  _get_fileinfo(); // get file information
137  rewind(); // position at BOS to start
138  return;
139 }
140 
141 // close the stream, by ending the GRI interface and closing the file
142 void hdfistream_gri::close(void)
143 {
144  _close_ri();
145  if (_gr_id != 0)
146  GRend(_gr_id);
147  if (_file_id != 0)
148  Hclose(_file_id);
149  _file_id = _gr_id = 0;
150  _nri = _nfattrs = 0;
151  return;
152 }
153 
154 // position to the stream to the index'th image
155 void hdfistream_gri::seek(int index)
156 {
157  if (_filename.length() == 0) // no file open
158  THROW(hcerr_invstream);
159  _close_ri();
160  _index = index;
161  _ri_id = GRselect(_gr_id, _index);
162  if (!eos() && !bos())
163  _get_iminfo();
164 }
165 
166 // position GRI stream to RI with name "name"
167 void hdfistream_gri::seek(const char *name)
168 {
169  if (_filename.length() == 0) // no open file
170  THROW(hcerr_invstream);
171  int32 index = GRnametoindex(_gr_id, (char *) name);
172  seek(index);
173 }
174 
175 // position GRI stream to RI with reference "ref"
176 void hdfistream_gri::seek_ref(int ref)
177 {
178  if (_filename.length() == 0) // no open file
179  THROW(hcerr_invstream);
180  int32 index = GRreftoindex(_gr_id, ref);
181  seek(index);
182 }
183 
184 // position GRI index in front of first RI
185 void hdfistream_gri::rewind(void)
186 {
187  if (_filename.length() == 0) // no file open
188  THROW(hcerr_invstream);
189  _close_ri(); // close any already open RI's
190  _rewind(); // seek to BOS
191 }
192 
193 // check to see if stream is positioned in front of
194 // the first RI in the file
195 bool hdfistream_gri::bos(void) const
196 {
197  if (_filename.length() == 0) // no file open
198  THROW(hcerr_invstream);
199  if (_nri == 0)
200  return false;
201  if (_index == -1)
202  return true;
203  else
204  return false;
205 }
206 
207 // check to see if stream has been positioned
208 // past the last RI in the file
209 bool hdfistream_gri::eos(void) const
210 {
211  if (_filename.length() == 0) // no file open
212  THROW(hcerr_invstream);
213  if (_nri == 0)
214  return true;
215  else {
216  if (bos())
217  return false;
218  else
219  return (_index >= _nri);
220  }
221 }
222 
223 // Check to see if stream is positioned past the last
224 // attribute in the currently open RI
225 bool hdfistream_gri::eo_attr(void) const
226 {
227  if (_filename.length() == 0)
228  THROW(hcerr_invstream);
229  if (eos())
230  return true;
231  else {
232  if (bos())
233  return (_attr_index >= _nfattrs);
234  else
235  return (_attr_index >= _nattrs);
236  }
237 }
238 
239 // Set interlace type for read into memory
240 void hdfistream_gri::setinterlace(int32 interlace_mode)
241 {
242  if (interlace_mode == MFGR_INTERLACE_PIXEL ||
243  interlace_mode == MFGR_INTERLACE_COMPONENT ||
244  interlace_mode == MFGR_INTERLACE_LINE)
245  _interlace_mode = interlace_mode;
246  else
247  THROW(hcerr_interlace);
248 }
249 
250 // check to see if stream is positioned past the last palette
251 // in the currently open RI
252 bool hdfistream_gri::eo_pal(void) const
253 {
254  if (_filename.length() == 0)
255  THROW(hcerr_invstream);
256  if (eos())
257  return true;
258  else {
259  if (bos())
260  return true;
261  else
262  return (_pal_index >= _npals);
263  }
264 }
265 
266 // set slab parameters
267 void hdfistream_gri::setslab(vector < int >start, vector < int >edge,
268  vector < int >stride, bool reduce_rank)
269 {
270  // check validity of input
271  if (start.size() != edge.size() || edge.size() != stride.size() ||
272  start.size() == 0)
273  THROW(hcerr_invslab);
274 
275  if (start.size() == 3) {
276  // erase # of components, if present: only X and Y subsetting allowed
277  start.erase(start.begin());
278  edge.erase(edge.begin());
279  stride.erase(stride.begin());
280  }
281 
282  for (int i = 0; i < 2; ++i) {
283  if (start[i] < 0)
284  THROW(hcerr_invslab);
285  if (edge[i] <= 0)
286  THROW(hcerr_invslab);
287  if (stride[i] <= 0)
288  THROW(hcerr_invslab);
289  // swap the X and Y dimensions because DODS prints data in [y][x] form
290  // but HDF wants dimensions in [x][y]
291  _slab.start[1 - i] = start[i];
292  _slab.edge[1 - i] = edge[i];
293  _slab.stride[1 - i] = stride[i];
294  }
295  _slab.set = true;
296  _slab.reduce_rank = reduce_rank;
297 }
298 
299 // read a single RI
300 hdfistream_gri & hdfistream_gri::operator>>(hdf_gri & hr)
301 {
302  if (_filename.length() == 0) // no file open
303  THROW(hcerr_invstream); // is this the right thing to throw?
304  // delete any prevous data in hr
305  hr.palettes = vector < hdf_palette > ();
306  hr.attrs = vector < hdf_attr > ();
307  hr.image = hdf_genvec();
308  hr.name = string();
309  if (bos())
310  seek(0);
311  if (eos())
312  return *this;
313  // get basic info about RI
314  char name[hdfclass::MAXSTR];
315  int32 ncomp;
316  int32 data_type;
317  int32 il;
318  int32 dim_sizes[2];
319  int32 nattrs;
320  if (GRgetiminfo
321  (_ri_id, name, &ncomp, &data_type, &il, dim_sizes, &nattrs) < 0)
322  THROW(hcerr_griinfo);
323  hr.ref = GRidtoref(_ri_id);
324  hr.name = name;
325  hr.dims[0] = dim_sizes[0];
326  hr.dims[1] = dim_sizes[1];
327  hr.num_comp = ncomp;
328  if (_interlace_mode == -1) {
329  setinterlace(il);
330  hr.interlace = il;
331  }
332  /* read in palettes */
333  *this >> hr.palettes;
334  *this >> hr.attrs;
335  if (_meta)
336  hr.image.import(data_type);
337  else {
338  int32 nelts;
339  char *image;
340  if (_slab.set) {
341  nelts = _slab.edge[0] * _slab.edge[1] * ncomp;
342  // allocate a temporary C array to hold the data from GRreadimage()
343  int imagesize = nelts * DFKNTsize(data_type);
344  image = new char[imagesize];
345  if (image == 0)
346  THROW(hcerr_nomemory);
347  // read the image and store it in a hdf_genvec
348  GRreqimageil(_ri_id, _interlace_mode);
349 #if 0
350  cerr << "ncomp: " << ncomp << " imagesize: " << imagesize <<
351  endl;
352  cerr << "_slab.start = " << _slab.start[0] << "," << _slab.
353  start[1] << " _slab.edge = " << _slab.
354  edge[0] << "," << _slab.
355  edge[1] << " _slab.stride = " << _slab.
356  stride[0] << "," << _slab.stride[1] << endl;
357 #endif
358  if (GRreadimage
359  (_ri_id, _slab.start, _slab.stride, _slab.edge,
360  image) < 0) {
361  delete[]image; // problem: clean up and throw an exception
362  THROW(hcerr_griread);
363  }
364  } else {
365  int32 zero[2];
366  zero[0] = zero[1] = 0;
367  nelts = dim_sizes[0] * dim_sizes[1] * ncomp;
368  // allocate a temporary C array to hold the data from GRreadimage()
369  int imagesize = nelts * DFKNTsize(data_type);
370  image = new char[imagesize];
371  if (image == 0)
372  THROW(hcerr_nomemory);
373  // read the image and store it in a hdf_genvec
374  GRreqimageil(_ri_id, _interlace_mode);
375 #if 0
376  cerr << "dim_sizes[0] = " << dim_sizes[0] << " dim_sizes[1] = "
377  << dim_sizes[1] << endl;
378 #endif
379  if (GRreadimage(_ri_id, zero, 0, dim_sizes, image) < 0) {
380  delete[]image; // problem: clean up and throw an exception
381  THROW(hcerr_griread);
382  }
383  }
384  // try { // try to import into an hdf_genvec
385  hr.image.import(data_type, image, nelts);
386  // }
387  // catch(...)
388  // delete [] image;
389  // throw;
390  // }
391  delete[]image; // deallocate temporary C array
392  }
393  seek_next(); // position to next RI
394  return *this;
395 }
396 
397 // read in all the RI's in a file
398 hdfistream_gri & hdfistream_gri::operator>>(vector < hdf_gri > &hrv)
399 {
400  for (hdf_gri gri; !eos();) {
401  *this >> gri;
402  hrv.push_back(gri);
403  }
404  return *this;
405 }
406 
407 // load attribute currently positioned at
408 hdfistream_gri & hdfistream_gri::operator>>(hdf_attr & ha)
409 {
410  if (_filename.length() == 0)
411  THROW(hcerr_invstream);
412  if (eo_attr())
413  return *this;
414  // prepare to read attribute information: set nattrs depending on whether
415  // reading file attributes or GRI attributes
416  int32 id;
417  //int nattrs;
418  if (bos()) {
419  //nattrs = _nfattrs;
420  id = _gr_id;
421  } else {
422  //nattrs = _nattrs;
423  id = _ri_id;
424  }
425  char name[hdfclass::MAXSTR];
426  int32 number_type, count;
427  if (GRattrinfo(id, _attr_index, name, &number_type, &count) < 0)
428  THROW(hcerr_griinfo);
429  // allocate a temporary C array to hold data from GRgetattr()
430  char *data;
431  data = new char[count * DFKNTsize(number_type)];
432  if (data == 0)
433  THROW(hcerr_nomemory);
434  // read attribute values and store them in an hdf_genvec
435  if (GRgetattr(id, _attr_index, data) < 0) {
436  delete[]data; // problem: clean up
437  THROW(hcerr_griinfo);
438  }
439  // eliminate trailing null characters from the data string
440  // they cause GNU's string class problems
441  if (number_type == DFNT_CHAR)
442  count = (int32) min((int) count, (int) strlen((char *) data));
443  // try { // try to allocate an hdf_genvec
444  if (count > 0) {
445  ha.values.import(number_type, data, count);
446 // }
447 // catch(...) { //problem allocating hdf_genvec: clean up and rethrow
448 // delete []data;
449 // throw;
450 // }
451  }
452  delete[]data;
453  ++_attr_index;
454  ha.name = name;
455  return *this;
456 }
457 
458 // read in all of the GRI attributes for currently open RI
459 hdfistream_gri & hdfistream_gri::operator>>(vector < hdf_attr > &hav)
460 {
461  for (hdf_attr att; !eo_attr();) {
462  *this >> att;
463  hav.push_back(att);
464  }
465  _attr_index = 0;
466  return *this;
467 }
468 
469 hdfistream_gri & hdfistream_gri::operator>>(hdf_palette & hp)
470 {
471  if (_filename.length() == 0) // no file open
472  THROW(hcerr_invstream);
473  if (eo_pal()) // if positioned past last dimension, do nothing
474  return *this;
475  // open palette currently positioned at and increment pal index
476  int32 pal_id;
477  if ((pal_id = GRgetlutid(_ri_id, _pal_index)) < 0)
478  THROW(hcerr_griinfo);
479  // get palette information;
480  int32 ncomp = 0, number_type = 0, num_entries = 0, junk0;
481  if (GRgetlutinfo(pal_id, &ncomp, &number_type, &junk0, &num_entries) <
482  0)
483  THROW(hcerr_griinfo);
484  else {
485  hp.ncomp = ncomp;
486  hp.num_entries = num_entries;
487  }
488  // Note: due to a bug in the HDF library, the palette number type is returned
489  // as DFNT_UCHAR8 instead of DFNT_UINT8. We correct that here because
490  // the current mapping for DFNT_UCHAR8 is string instead of Byte
491  if (number_type == DFNT_UCHAR8)
492  number_type = DFNT_UINT8;
493 
494  int32 count = ncomp * num_entries;
495  if (number_type != 0) { // found a palette
496  char *pal_data;
497  pal_data = new char[count * DFKNTsize(number_type)];
498  if (pal_data == 0)
499  THROW(hcerr_nomemory);
500  // read the palette data and store it in an hdf_genvec
501  GRreqlutil(pal_id, MFGR_INTERLACE_PIXEL);
502  if (GRreadlut(pal_id, pal_data) < 0) {
503  delete[]pal_data; // problem: clean up and
504  THROW(hcerr_griinfo); // throw an exception
505  }
506  // try { // problem allocating hdf_genvec: clean up and rethrow
507  hp.table.import(number_type, pal_data, count);
508  // }
509  // catch(...) { // problem allocating hdf_genvec: clean up and rethrow
510  // delete []data;
511  // throw;
512  // }
513  delete[]pal_data; // deallocating temporary C array
514  }
515  ++_pal_index;
516  return *this;
517 }
518 
519 // read in all of the RI palettes for the currently open RI
520 hdfistream_gri & hdfistream_gri::operator>>(vector < hdf_palette > &hpv)
521 {
522  for (hdf_palette pal; !eo_pal();) {
523  *this >> pal;
524  hpv.push_back(pal);
525  }
526  return *this;
527 }
528 
529 // Verify that the hdf_gri is in an OK state (i.e., that it is initialized correctly)
530 // if user has passed a ptr to a bool then set that to whether there is a dimension
531 // scale
532 bool hdf_gri::_ok() const
533 {
534  // The image should have the same number of components as indicated
535  // by the number of dimensions and number of componets
536  bool ok = (dims[0] * dims[1] * num_comp == image.size());
537  if (!ok)
538  return (ok);
539  if (has_palette())
540  for (int i = 0; i < int (palettes.size()) && ok; i++)
541  ok = (palettes[i].ncomp * palettes[i].num_entries ==
542  palettes[i].table.size());
543  return (ok);
544 }
545 
546 // $Log: gri.cc,v $
547 // Revision 1.9.4.1.2.1 2004/02/23 02:08:03 rmorris
548 // There is some incompatibility between the use of isascii() in the hdf library
549 // and its use on OS X. Here we force in the #undef of isascii in the osx case.
550 //
551 // Revision 1.9.4.1 2003/05/21 16:26:58 edavis
552 // Updated/corrected copyright statements.
553 //
554 // Revision 1.9 2003/01/31 02:08:37 jimg
555 // Merged with release-3-2-7.
556 //
557 // Revision 1.8.4.2 2002/12/18 23:32:50 pwest
558 // gcc3.2 compile corrections, mainly regarding the using statement. Also,
559 // missing semicolon in .y file
560 //
561 // Revision 1.8.4.1 2001/10/30 06:36:35 jimg
562 // Added genvec::append(...) method.
563 // Fixed up some comments in genvec.
564 // Changed genvec's data member from void * to char * to quell warnings
565 // about void * being passed to delete.
566 //
567 // Revision 1.8 2000/10/09 19:46:19 jimg
568 // Moved the CVS Log entries to the end of each file.
569 // Added code to catch Error objects thrown by the dap library.
570 // Changed the read() method's definition to match the dap library.
571 //
572 // Revision 1.7 2000/03/31 16:56:05 jimg
573 // Merged with release 3.1.4
574 //
575 // Revision 1.6.8.1 2000/03/20 23:26:07 jimg
576 // Removed debugging output
577 //
578 // Revision 1.6 1999/05/06 03:23:33 jimg
579 // Merged changes from no-gnu branch
580 //
581 // Revision 1.5 1999/05/05 23:33:43 jimg
582 // String --> string conversion
583 //
584 // Revision 1.4.6.1 1999/05/06 00:35:45 jimg
585 // Jakes String --> string changes
586 //
587 // Revision 1.4 1998/09/10 21:50:22 jehamby
588 // Fix subsetting for multi-component GR (Note: due to an HDF library bug,
589 // you can't actually subset a GR with >1 component, but at least retrieving
590 // the entire image works). Also, remove debugging output and work around
591 // another HDF bug so palettes output as Byte instead of string.
592 //
593 // Revision 1.3 1998/07/13 20:26:35 jimg
594 // Fixes from the final test of the new build process
595 //
596 // Revision 1.2.4.1 1998/05/22 19:50:51 jimg
597 // Patch from Jake Hamby to support subsetting raster images
598 //
599 // Revision 1.2 1998/04/03 18:34:17 jimg
600 // Fixes for vgroups and Sequences from Jake Hamby
601 //
602 // Revision 1.1 1996/10/31 18:42:58 jimg
603 // Added.
604 //
605 // Revision 1.10 1996/09/20 20:25:48 ike
606 // Changed meta behavior for rasters. Palletes are now read when meta is true.
607 //
608 // Revision 1.9 1996/09/20 18:28:40 ike
609 // Fixed GR reading to read images in there native interace by default.
610 //
611 // Revision 1.8 1996/09/20 17:49:55 ike
612 // Added setinterlace() to set the interlace type for reading images.
613 // Used GRreqlutil to for palletes to be read in pixel interlace.
614 //
615 // Revision 1.7 1996/08/22 20:56:36 todd
616 // Corrected bug in destructor. Cleaned up initializations.
617 //
618 // Revision 1.6 1996/07/22 17:15:09 todd
619 // Const-corrected hdfistream_gri::seek() routine.
620 //
621 // Revision 1.5 1996/06/18 22:06:19 ike
622 // Removed default argument values from argument lists.
623 //
624 // Revision 1.4 1996/06/18 01:13:20 ike
625 // Fixed infinite loop caused by problem incrementing _nattrs, _nfattrs.
626 // Added _ok(), !operator, and has_palette to hdf_gri.
627 //
628 // Revision 1.3 1996/06/18 00:57:13 todd
629 // Added hcerr.h include at top of module.
630 //
631 // Revision 1.2 1996/06/14 21:58:45 ike
632 // fixed operator>> to overwrite non vectors objects.
633 //
634 // Revision 1.1 1996/06/14 21:53:09 ike
635 // Initial revision
636 //
hdfistream_gri
Definition: hcstream.h:395
hcerr_invstream
Definition: hcerr.h:111
hcerr_griread
Definition: hcerr.h:317
hdfistream_obj
Definition: hcstream.h:51
hcerr_openfile
Definition: hcerr.h:125
hcerr_nomemory
Definition: hcerr.h:97
hdf_gri
Definition: hdfclass.h:243
hdf_palette
Definition: hdfclass.h:234
hcerr_invslab
Definition: hcerr.h:324
hcerr_griinfo
Definition: hcerr.h:310
hdf_genvec
Definition: hdfclass.h:71
hcerr_interlace
Definition: hcerr.h:331
hdf_attr
Definition: hdfclass.h:149