vil_geotiff_header.cxx
Go to the documentation of this file.
1 #include <cstdlib>
2 #include <iostream>
3 #include "vil_geotiff_header.h"
4 //:
5 // \file
6 #include <cassert>
7 #ifdef _MSC_VER
8 # include <vcl_msvc_warnings.h>
9 #endif
10 #include <geo_tiffp.h>
11 #include <geotiffio.h>
12 #include <geovalues.h>
13 
15 {
16  if (tif) {
17  gtif_ = GTIFNew(tif);
18  if (gtif_) {
19  GTIFPrint(gtif_, nullptr, nullptr);
20 
21  // read the header of the GeoDirectoryKey Tag
22  int version[3];
23  GTIFDirectoryInfo(gtif_, version, &number_of_geokeys_);
24  key_directory_version_ = (unsigned short)version[0];
25  key_revision_ = (unsigned short)version[1];
26  minor_revision_ = (unsigned short)version[2];
27  }
28  }
29 }
30 
31 bool vil_geotiff_header::gtif_tiepoints(std::vector<std::vector<double> > &tiepoints)
32 {
33  double* points=nullptr;
34  short count;
35  if (TIFFGetField(tif_, GTIFF_TIEPOINTS, &count, &points) < 0)
36  return false;
37 
38  // tiepoints are stored as 3d points (I,J,K)->(X,Y,Z)
39  // where the point at location (I,J) at raster space with pixel value K
40  // and (X,Y,Z) is a vector in model space
41 
42  // the number of values should be K*6
43  assert((count % 6) == 0);
44  for (unsigned short i=0; i<count; ) {
45  std::vector<double> tiepoint(6);
46  tiepoint[0] = points[i++];
47  tiepoint[1] = points[i++];
48  tiepoint[2] = points[i++];
49  tiepoint[3] = points[i++];
50  tiepoint[4] = points[i++];
51  tiepoint[5] = points[i++];
52  tiepoints.push_back(tiepoint);
53  }
54  return true;
55 }
56 
57 bool vil_geotiff_header::gtif_pixelscale(double &scale_x, double &scale_y, double &scale_z)
58 {
59  double *data;
60  short count;
61  if (TIFFGetField(tif_, GTIFF_PIXELSCALE, &count, &data )) {
62  assert (count == 3);
63  scale_x = data[0];
64  scale_y = data[1];
65  scale_z = data[2];
66  return true;
67  }
68  else
69  return false;
70 }
71 
72 bool vil_geotiff_header::gtif_trans_matrix (double* &trans_matrix)
73 {
74  short count;
75  if (TIFFGetField(tif_, GTIFF_TRANSMATRIX, &count, &trans_matrix )) {
76  assert (count == 16);
77  return true;
78  }
79  else
80  return false;
81 }
82 
83 bool vil_geotiff_header::gtif_modeltype (modeltype_t& type)
84 {
85  geocode_t model;
86  if (!GTIFKeyGet(gtif_, GTModelTypeGeoKey, &model, 0, 1)) {
87  std::cerr << "NO Model Type defined!!!!\n";
88  return false;
89  }
90  else {
91  type = static_cast<modeltype_t> (model);
92  return true;
93  }
94 }
95 
96 bool vil_geotiff_header::gtif_rastertype (rastertype_t& type)
97 {
98  geocode_t raster;
99  if (!GTIFKeyGet(gtif_, GTRasterTypeGeoKey, &raster, 0, 1)) {
100  std::cerr << "NO Raster Type, failure!!!!\n";
101  return false;
102  }
103  else {
104  type = static_cast<rastertype_t> (raster);
105  return true;
106  }
107 }
108 
109 bool vil_geotiff_header::geounits (geounits_t& units)
110 {
111  short nGeogUOMLinear;
112  if (!GTIFKeyGet(gtif_, GeogLinearUnitsGeoKey, &nGeogUOMLinear, 0, 1 )) {
113  std::cerr << "NO GEOUNITS, failure!!!!\n";
114  return false;
115  }
116  else {
117  units = static_cast<geounits_t> (nGeogUOMLinear);
118  return true;
119  }
120 }
121 
122 bool vil_geotiff_header::PCS_WGS84_UTM_zone(int &zone, GTIF_HEMISPH &hemisph) // hemisph is O for N, 1 for S
123 {
124  modeltype_t type;
125  if (gtif_modeltype(type) && type == ModelTypeProjected)
126  {
127  void *value;
128  int size;
129  int length;
130  tagtype_t ttype;
131  bool status = get_key_value(ProjectedCSTypeGeoKey, &value, size, length, ttype);
132  if (!status) {
133  std::cerr << "Missing ProjectedCSTypeGeoKey (" << ProjectedCSTypeGeoKey << ") key!\n";
134  return false;
135  }
136 
137  // WGS84 / UTM northern hemisphere: 326zz where zz is UTM zone number
138  // WGS84 / UTM southern hemisphere: 327zz where zz is UTM zone number
139  // we are looking for a short value, only one
140  if(length != 1 || ttype != TYPE_SHORT) {
141  std::cerr << "Expected a single value with type int16 (short)!\n";
142  return false;
143  }
144 
145  auto *val = static_cast<short*> (value);
146  if ((*val < PCS_WGS84_UTM_zone_1N ) || ((*val > PCS_WGS84_UTM_zone_60S ))) {
147  return false;
148  }
149 
150 #if 0
151  int zone;
152  int hemisph; // O for N, 1 for S
153 #endif // 0
154  if ((*val >= PCS_WGS84_UTM_zone_1N) && (*val <= PCS_WGS84_UTM_zone_60N)) {
155  zone = *val - 32600;
156  hemisph = NORTH;
157  }
158  else if ((*val >= PCS_WGS84_UTM_zone_1S) && (*val <= PCS_WGS84_UTM_zone_60S)) {
159  zone = *val - 32700;
160  hemisph = SOUTH;
161  }
162  return true;
163  }
164  else {
165  hemisph = UNDEF;
166  return false;
167  }
168 }
169 
170 //: returns true if in geographic coords, linear units are in meters and angular units are in degrees
172 {
173  modeltype_t type;
174  if (gtif_modeltype(type) && type == ModelTypeGeographic) {
175  void *value; int size; int length; tagtype_t ttype;
176 
177  bool status = get_key_value(GeogLinearUnitsGeoKey, &value, size, length, ttype);
178  if (!status) {
179  std::cerr << "Missing GeogLinearUnitsGeoKey (" << GeogLinearUnitsGeoKey << ") key!\n";
180  return false;
181  }
182  if(length != 1 || ttype != TYPE_SHORT) {
183  std::cerr << "Expected a single value with type int16 (short)!\n";
184  return false;
185  }
186  auto *val = static_cast<short*> (value);
187 
188  if (*val != Linear_Meter) {
189  std::cerr << "Linear units are not in Meters!\n";
190  return false;
191  }
192 
193  status = get_key_value(GeogAngularUnitsGeoKey, &value, size, length, ttype);
194  if (!status) {
195  std::cerr << "Missing GeogAngularUnitsGeoKey (" << GeogAngularUnitsGeoKey << ") key!\n";
196  return false;
197  }
198  if(length != 1 || ttype != TYPE_SHORT) {
199  std::cerr << "Expected a single value with type int16 (short)!\n";
200  return false;
201  }
202  val = static_cast<short*> (value);
203 
204  if (*val != Angular_Degree) {
205  std::cerr << "Angular units are not in Degrees!\n";
206  return false;
207  }
208 
209  return true;
210  }
211  return false;
212 }
213 
214 //: returns the Zone and the Hemisphere (0 for N, 1 for S);
216 {
217  modeltype_t type;
218  if (gtif_modeltype(type) && type == ModelTypeProjected)
219  {
220  void *value;
221  int size;
222  int length;
223  tagtype_t ttype;
224  bool status = get_key_value(ProjectedCSTypeGeoKey, &value, size, length, ttype);
225  if (!status) {
226  std::cerr << "Missing ProjectedCSTypeGeoKey (" << ProjectedCSTypeGeoKey << ") key!\n";
227  return false;
228  }
229  if(length != 1 || ttype != TYPE_SHORT) {
230  std::cerr << "Expected a single value with type int16 (short)!\n";
231  return false;
232  }
233 
234  auto *val = static_cast<short*> (value);
235  if ((*val < PCS_NAD83_UTM_zone_3N ) || ((*val > PCS_NAD83_Missouri_West ))) {
236  std::cerr << "NOT in RANGE PCS_NAD83_UTM_zone_3N and PCS_NAD83_Missouri_West!\n";
237  return false;
238  }
239  zone = *val - 26900;
240  hemisph = NORTH;
241 
242  return true;
243  }
244  else {
245  hemisph = UNDEF;
246  return false;
247  }
248 }
249 
250 
251 bool vil_geotiff_header::get_key_value(geokey_t key, void** value,
252  int& size, int& length, tagtype_t& type)
253 {
254  length = GTIFKeyInfo(gtif_, key, &size, &type);
255 
256  // check if it is a valid key id
257  if (length == 0) {
258  // key is not defined
259  std::cerr << "KeyID=" << (short int)key << " is not valid\n";
260  return false;
261  }
262  else {
263  *value = std::malloc(size*length);
264  GTIFKeyGet(gtif_, key, *value, 0, length);
265  return true;
266  }
267 }
unsigned short key_revision_
unsigned short key_directory_version_
bool gtif_tiepoints(std::vector< std::vector< double > > &tiepoints)
bool gtif_trans_matrix(double *&trans_matrix)
returns the matrix in the argument.
unsigned short minor_revision_
bool get_key_value(geokey_t key, void **value, int &size, int &length, tagtype_t &type)
<key> : key id.
bool gtif_pixelscale(double &scale_x, double &scale_y, double &scale_z)
bool PCS_WGS84_UTM_zone(int &zone, GTIF_HEMISPH &hemisph)
returns the Zone and the Hemisphere (0 for N, 1 for S);.
bool GCS_WGS84_MET_DEG()
returns true if in geographic coords, linear units are in meters and angular units are in degrees.
bool geounits(geounits_t &)
bool gtif_modeltype(modeltype_t &type)
bool gtif_rastertype(rastertype_t &)
A header structure for geotiff files.
bool PCS_NAD83_UTM_zone(int &zone, GTIF_HEMISPH &hemisph)
returns the Zone and the Hemisphere (0 for N, 1 for S);.