Isis 3 Programmer Reference
TiffImporter.cpp
1 #include <iostream>
2 #include <iomanip>
3 
4 #include <QDebug>
5 #include <QDomDocument>
6 #include <QDomElement>
7 #include <QDomNode>
8 
9 #include "TiffImporter.h"
10 
11 #include "Angle.h"
12 #include "FileName.h"
13 #include "IException.h"
14 #include "IString.h"
15 #include "ProjectionFactory.h"
16 #include "Pvl.h"
17 #include "PvlGroup.h"
19 #include "TProjection.h"
20 
21 namespace Isis {
28 
29  // Open the TIFF image
30  m_image = NULL;
31  if ((m_image = XTIFFOpen(inputName.expanded().toLatin1().data(), "r")) == NULL) {
33  QString("Could not open TIFF image [") + inputName.expanded().toLatin1().data() + "]", _FILEINFO_);
34  }
35 
36  // Get its constant dimensions. Note, height seems to get reset to 0 if
37  // called before setting width.
38  uint32 height;
39  TIFFGetField(m_image, TIFFTAG_IMAGELENGTH, &height);
40  setLines(height);
41 
42  uint32 width;
43  TIFFGetField(m_image, TIFFTAG_IMAGEWIDTH, &width);
44  setSamples(width);
45 
46  TIFFGetField(m_image, TIFFTAG_SAMPLESPERPIXEL, &m_samplesPerPixel);
47 
48  // Setup the width and height of the image
49  unsigned long imagesize = lines() * samples();
50  m_raster = NULL;
51  if ((m_raster = (uint32 *) malloc(sizeof(uint32) * imagesize)) == NULL) {
53  "Could not allocate enough memory", _FILEINFO_);
54  }
55 
56  // Read the image into the memory buffer
57  if (TIFFReadRGBAImage(m_image, samples(), lines(), m_raster, 0) == 0) {
59  "Could not read image", _FILEINFO_);
60  }
61 
62  // Deal with photometric interpretations
63  if (TIFFGetField(m_image, TIFFTAG_PHOTOMETRIC, &m_photo) == 0) {
65  "Image has an undefined photometric interpretation", _FILEINFO_);
66  }
67 
68  // Get the geotiff info (if available)
69  m_geotiff = NULL;
70  m_geotiff = GTIFNew(m_image);
71 
73  }
74 
75 
80  free(m_raster);
81  m_raster = NULL;
82 
83  GTIFFree(m_geotiff);
84  m_geotiff = NULL;
85 
86  XTIFFClose(m_image);
87  m_image = NULL;
88  }
89 
90 
105 
106  Pvl outPvl;
107  outPvl.addGroup(PvlGroup("Mapping"));
108 
109  geocode_t modelType;
110  geocode_t rasterType;
111  geocode_t coordSysType;
112 
113  if ((GTIFKeyGet(m_geotiff, GTModelTypeGeoKey, &modelType, 0, 1) == 1) &&
114  ((modelType == 1) || (modelType == 2))) { // 1=ModelTypeProjected, 2=ModelTypeGeographic
115 
116  if ((GTIFKeyGet(m_geotiff, GTRasterTypeGeoKey, &rasterType, 0, 1) == 1) &&
117  (rasterType == 1 || rasterType == 2)) { // Area || Point
118 
119  // See if this geogiff uses a coded projection. That is, the projection parameters are not
120  // explicitly set. A code in the GEOTIF tag indicates a set of parameters for this
121  // projection.
122  if (GTIFKeyGet(m_geotiff, ProjectedCSTypeGeoKey, &coordSysType, 0, 1) == 1) {
123 
124  // Get the mapping group data for this code: proj name, clat, clon, ...
125  FileName transFile((QString) "$base/translations/geotiff/" +
126  toString(coordSysType) + ".trn");
127  if (transFile.fileExists()) {
128  Pvl tmp;
129  tmp += PvlKeyword("Code", toString(coordSysType));
130  PvlToPvlTranslationManager geoTiffCodeTranslater(tmp, transFile.expanded());
131  geoTiffCodeTranslater.Auto(outPvl);
132  }
133  }
134 
135  // The following is here for when this gets generalized to handle non coded projections
136  // (i.e., the real proj parameters have values and the code is not used)
137  else if (1 == 0) {
138  geocode_t geoCode;
139  if (GTIFKeyGet(m_geotiff, GeographicTypeGeoKey, &geoCode, 0, 1) == 1) {
140  std::cout << "GeographicTypeGeoKey = " << geoCode << std::endl;
141  }
142  else {
143  std::cout << "no GeographicTypeGeoKey" << std::endl;
144  }
145 
146  if (GTIFKeyGet(m_geotiff, GeogAngularUnitsGeoKey, &geoCode, 0, 1) == 1) {
147  std::cout << "GeogAngularUnitsGeoKey = " << geoCode << std::endl;
148  }
149  else {
150  std::cout << "no GeogAngularUnitsGeoKey" << std::endl;
151  }
152 
153  if (GTIFKeyGet(m_geotiff, GeogEllipsoidGeoKey, &geoCode, 0, 1) == 1) {
154  std::cout << "GeogEllipsoidGeoKey = " << geoCode << std::endl;
155  }
156  else {
157  std::cout << "no GeogEllipsoidGeoKey" << std::endl;
158  }
159 
160  if (GTIFKeyGet(m_geotiff, GeogSemiMajorAxisGeoKey, &geoCode, 0, 1) == 1) {
161  std::cout << "GeogSemiMajorAxisGeoKey = " << geoCode << std::endl;
162  }
163  else {
164  std::cout << "no GeogSemiMajorAxisGeoKey" << std::endl;
165  }
166 
167  if (GTIFKeyGet(m_geotiff, GeogSemiMinorAxisGeoKey, &geoCode, 0, 1) == 1) {
168  std::cout << "GeogSemiMinorAxisGeoKey = " << geoCode << std::endl;
169  }
170  else {
171  std::cout << "no GeogSemiMinorAxisGeoKey" << std::endl;
172  }
173 
174  if (GTIFKeyGet(m_geotiff, GeogInvFlatteningGeoKey, &geoCode, 0, 1) == 1) {
175  std::cout << "GeogInvFlatteningGeoKey = " << geoCode << std::endl;
176  }
177  else {
178  std::cout << "no GeogInvFlatteningGeoKey" << std::endl;
179  }
180 
181  if (GTIFKeyGet(m_geotiff, ProjCoordTransGeoKey, &geoCode, 0, 1) == 1) {
182  std::cout << "ProjCoordTransGeoKey = " << geoCode << std::endl;
183  }
184  else {
185  std::cout << "no ProjCoordTransGeoKey" << std::endl;
186  }
187 
188  if (GTIFKeyGet(m_geotiff, ProjLinearUnitsGeoKey, &geoCode, 0, 1) == 1) {
189  std::cout << "ProjLinearUnitsGeoKey = " << geoCode << std::endl;
190  }
191  else {
192  std::cout << "no ProjLinearUnitsGeoKey" << std::endl;
193  }
194 
195  if (GTIFKeyGet(m_geotiff, ProjStdParallel1GeoKey, &geoCode, 0, 1) == 1) {
196  std::cout << "ProjStdParallel1GeoKey = " << geoCode << std::endl;
197  }
198  else {
199  std::cout << "no ProjStdParallel1GeoKey" << std::endl;
200  }
201 
202  if (GTIFKeyGet(m_geotiff, ProjStdParallel2GeoKey, &geoCode, 0, 1) == 1) {
203  std::cout << "ProjStdParallel2GeoKey = " << geoCode << std::endl;
204  }
205  else {
206  std::cout << "no ProjStdParallel2GeoKey" << std::endl;
207  }
208 
209  if (GTIFKeyGet(m_geotiff, ProjNatOriginLongGeoKey, &geoCode, 0, 1) == 1) {
210  std::cout << "ProjNatOriginLongGeoKey = " << geoCode << std::endl;
211  }
212  else {
213  std::cout << "no ProjNatOriginLongGeoKey" << std::endl;
214  }
215 
216  if (GTIFKeyGet(m_geotiff, ProjNatOriginLatGeoKey, &geoCode, 0, 1) == 1) {
217  std::cout << "ProjNatOriginLatGeoKey = " << geoCode << std::endl;
218  }
219  else {
220  std::cout << "no ProjNatOriginLatGeoKey" << std::endl;
221  }
222 
223  if (GTIFKeyGet(m_geotiff, ProjFalseEastingGeoKey, &geoCode, 0, 1) == 1) {
224  std::cout << "ProjFalseEastingGeoKey = " << geoCode << std::endl;
225  }
226  else {
227  std::cout << "no ProjFalseEastingGeoKey" << std::endl;
228  }
229 
230  if (GTIFKeyGet(m_geotiff, ProjFalseNorthingGeoKey, &geoCode, 0, 1) == 1) {
231  std::cout << "ProjFalseNorthingGeoKey = " << geoCode << std::endl;
232  }
233  else {
234  std::cout << "no ProjFalseNorthingGeoKey" << std::endl;
235  }
236 
237  if (GTIFKeyGet(m_geotiff, ProjFalseOriginLongGeoKey, &geoCode, 0, 1) == 1) {
238  std::cout << "ProjFalseOriginLongGeoKey = " << geoCode << std::endl;
239  }
240  else {
241  std::cout << "no ProjFalseOriginLongGeoKey" << std::endl;
242  }
243 
244  if (GTIFKeyGet(m_geotiff, ProjFalseOriginLatGeoKey, &geoCode, 0, 1) == 1) {
245  std::cout << "ProjFalseOriginLatGeoKey = " << geoCode << std::endl;
246  }
247  else {
248  std::cout << "no ProjFalseOriginLatGeoKey" << std::endl;
249  }
250 
251  if (GTIFKeyGet(m_geotiff, ProjFalseOriginEastingGeoKey, &geoCode, 0, 1) == 1) {
252  std::cout << "ProjFalseOriginEastingGeoKey = " << geoCode << std::endl;
253  }
254  else {
255  std::cout << "no ProjFalseOriginEastingGeoKey" << std::endl;
256  }
257 
258  if (GTIFKeyGet(m_geotiff, ProjFalseOriginNorthingGeoKey, &geoCode, 0, 1) == 1) {
259  std::cout << "ProjFalseOriginNorthingGeoKey = " << geoCode << std::endl;
260  }
261  else {
262  std::cout << "no ProjFalseOriginNorthingGeoKey" << std::endl;
263  }
264 
265  if (GTIFKeyGet(m_geotiff, ProjCenterLongGeoKey, &geoCode, 0, 1) == 1) {
266  std::cout << "ProjCenterLongGeoKey = " << geoCode << std::endl;
267  }
268  else {
269  std::cout << "no ProjCenterLongGeoKey" << std::endl;
270  }
271 
272  if (GTIFKeyGet(m_geotiff, ProjCenterLatGeoKey, &geoCode, 0, 1) == 1) {
273  std::cout << "ProjCenterLatGeoKey = " << geoCode << std::endl;
274  }
275  else {
276  std::cout << "no ProjCenterLatGeoKey" << std::endl;
277  }
278 
279  if (GTIFKeyGet(m_geotiff, ProjCenterEastingGeoKey, &geoCode, 0, 1) == 1) {
280  std::cout << "ProjCenterEastingGeoKey = " << geoCode << std::endl;
281  }
282  else {
283  std::cout << "no ProjCenterEastingGeoKey" << std::endl;
284  }
285 
286  if (GTIFKeyGet(m_geotiff, ProjCenterNorthingGeoKey, &geoCode, 0, 1) == 1) {
287  std::cout << "ProjCenterNorthingGeoKey = " << geoCode << std::endl;
288  }
289  else {
290  std::cout << "no ProjCenterNorthingGeoKey" << std::endl;
291  }
292 
293  if (GTIFKeyGet(m_geotiff, ProjScaleAtNatOriginGeoKey, &geoCode, 0, 1) == 1) {
294  std::cout << "ProjScaleAtNatOriginGeoKey = " << geoCode << std::endl;
295  }
296  else {
297  std::cout << "no ProjScaleAtNatOriginGeoKey" << std::endl;
298  }
299 
300  if (GTIFKeyGet(m_geotiff, ProjAzimuthAngleGeoKey, &geoCode, 0, 1) == 1) {
301  std::cout << "ProjAzimuthAngleGeoKey = " << geoCode << std::endl;
302  }
303  else {
304  std::cout << "no ProjAzimuthAngleGeoKey" << std::endl;
305  }
306 
307  if (GTIFKeyGet(m_geotiff, ProjStraightVertPoleLongGeoKey, &geoCode, 0, 1) == 1) {
308  std::cout << "ProjStraightVertPoleLongGeoKey = " << geoCode << std::endl;
309  }
310  else {
311  std::cout << "no ProjStraightVertPoleLongGeoKey" << std::endl;
312  }
313 
314  if (GTIFKeyGet(m_geotiff, VerticalUnitsGeoKey, &geoCode, 0, 1) == 1) {
315  std::cout << "VerticalUnitsGeoKey = " << geoCode << std::endl;
316  }
317  else {
318  std::cout << "no VerticalUnitsGeoKey" << std::endl;
319  }
320  } // End of individual GEOTIFF projection parameters
321 
322  // There are some projections parameters that are not in the GEO part of the TIFF, get them
323 
324  // Get the Tiff Tiepoint tag and convert those to Upper Left X & Y
325  outPvl = upperLeftXY(outPvl);
326 
327  // Get the Tiff PixelScale tag and convert it to resolution and scale
328  outPvl = resolution(outPvl);
329 
330  // Get the GDAL minimum and maximum lats and lons
331  outPvl = gdalItems(outPvl);
332 
333  } // End of raster type
334 
335 
336  // Test the projection
337  // If any things goes wrong just ignore the projection and move on
338  try {
339  TProjection *proj = NULL;
340  proj = (TProjection *) ProjectionFactory::Create(outPvl);
341 
342  PvlGroup &mapGroup = outPvl.findGroup("Mapping");
343  double pixelResolution = mapGroup["PixelResolution"];
344  double trueScaleLat = proj->TrueScaleLatitude();
345  double localRadius = proj->LocalRadius(trueScaleLat);
346 
347  double scale = (2.0 * Isis::PI * localRadius) / (360.0 * pixelResolution);
348  mapGroup += PvlKeyword("Scale", toString(scale), "pixels/degree");
349  }
350  catch (IException &e) {
351  outPvl.findGroup("Mapping").clear();
352  }
353  }
354 
355  return outPvl.findGroup("Mapping");
356  }
357 
358 
365  Pvl TiffImporter::gdalItems(const Pvl &inLab) const {
366 
367  Pvl newLab = inLab;
368  PvlGroup &map = newLab.findGroup("Mapping");
369 
370  // Get the GDALMetadata tag (42112) to get the lat/lon boundry
371  char *gdalMetadataBuf;
372  short int gdalMetadataCount = 0;
373 
374  if (TIFFGetField(m_image, 42112, &gdalMetadataCount, &gdalMetadataBuf) == 1) {
375 
376  QString gdalMetadataQstring(gdalMetadataBuf);
377 
378  QDomDocument gdalDoc("GDALMetaData");
379  if (gdalDoc.setContent(gdalMetadataQstring)) {
380  QDomElement gdalRoot = gdalDoc.documentElement();
381  if (gdalRoot.tagName() == "GDALMetadata") {
382 
383  QDomNode gdalNode = gdalRoot.firstChild();
384  while (!gdalNode.isNull()) {
385  QDomElement gdalElement = gdalNode.toElement();
386  if (!gdalElement.isNull() ) {
387  if (gdalElement.tagName() == "Item") {
388  if (gdalElement.attribute("name", "") == "WEST_LONGITUDE") {
389  QString westLon = gdalElement.text();
390  map += PvlKeyword("MinimumLongitude", toString(Angle(westLon).degrees()));
391  }
392  else if (gdalElement.attribute("name", "") == "EAST_LONGITUDE") {
393  QString eastLon = gdalElement.text();
394  map += PvlKeyword("MaximumLongitude", toString(Angle(eastLon).degrees()));
395  }
396  else if (gdalElement.attribute("name", "") == "SOUTH_LATITUDE") {
397  QString southLat = gdalElement.text();
398  map += PvlKeyword("MinimumLatitude", toString(Angle(southLat).degrees()));
399  }
400  else if (gdalElement.attribute("name", "") == "NORTH_LATITUDE") {
401  QString northLat = gdalElement.text();
402  map += PvlKeyword("MaximumLatitude", toString(Angle(northLat).degrees()));
403  }
404  }
405  }
406 
407  gdalNode = gdalNode.nextSibling();
408  }
409  }
410  }
411  }
412 
413  return newLab;
414  }
415 
416 
424  Pvl TiffImporter::upperLeftXY(const Pvl &inLab) const {
425 
426  Pvl newLab = inLab;
427  PvlGroup &map = newLab.findGroup("Mapping");
428 
429  double *tiePoints = NULL;
430  short int tieCount = 0;
431  if (TIFFGetField(m_image, TIFFTAG_GEOTIEPOINTS, &tieCount, &tiePoints) == 1) {
432 
433  // The expected tiepoints are TIFF(i, j, k, x, y, z) = ISIS(sample, line, 0, X, Y, 0)
434  // Make sure the (x, y) refer to the (0, 0)
435  if (tiePoints[0] == 0.0 && tiePoints[1] == 0.0) {
436  double x = 0.0;
437  if (map.hasKeyword("FalseEasting")) {
438  x = (double)map["FalseEasting"] + tiePoints[3];
439  map.deleteKeyword("FalseEasting");
440  }
441 
442  double y = 0.0;
443  if (map.hasKeyword("FalseNorthing")) {
444  y = (double)map["FalseNorthing"] + tiePoints[4];
445  map.deleteKeyword("FalseNorthing");
446  }
447 
448  map += PvlKeyword("UpperLeftCornerX", toString(x), "meters");
449  map += PvlKeyword("UpperLeftCornerY", toString(y), "meters");
450  }
451  else {
452  QString msg = "The upper left X and Y can not be calculated. Unsupported tiepoint "
453  "type in Tiff file (i.e., not ( 0.0, 0.0))";
455  }
456  }
457 
458  return newLab;
459  }
460 
461 
469  Pvl TiffImporter::resolution(const Pvl &inLab) const {
470 
471  Pvl newLab = inLab;
472  PvlGroup &map = newLab.findGroup("Mapping");
473 
474  // Get the Tiff PixelScale tag and convert it to resolution
475  double *scales = NULL;
476  short int scaleCount = 0;
477  if (TIFFGetField(m_image, TIFFTAG_GEOPIXELSCALE, &scaleCount, &scales) == 1) {
478 
479  // The expected scales are TIFF(x, y, z) = ISIS(sample, line, 0)
480  // Make sure the (x, y) are the same but not zero (0) for ISIS
481  if ((scaleCount == 3) && (scales[0] > 0.0 && scales[1] > 0.0) && (scales[0] == scales[1])) {
482  map += PvlKeyword("PixelResolution", toString(scales[0]), "meters");
483  }
484  else {
485  QString msg = "The pixel resolution could not be retrieved from the TIFF file. Unsupported "
486  "PixelScale tag values.";
488  }
489  }
490 
491  return newLab;
492  }
493 
494 
505  return m_samplesPerPixel;
506  }
507 
508 
516  return
517  m_photo == PHOTOMETRIC_MINISWHITE ||
518  m_photo == PHOTOMETRIC_MINISBLACK;
519  }
520 
521 
528  bool TiffImporter::isRgb() const {
529  return !isGrayscale() && samplesPerPixel() <= 3;
530  }
531 
532 
539  bool TiffImporter::isArgb() const {
540  return !isGrayscale() && samplesPerPixel() > 3;
541  }
542 
543 
551  void TiffImporter::updateRawBuffer(int line, int band) const {
552  }
553 
554 
565  int TiffImporter::getPixel(int s, int l) const {
566  l = lines() - l - 1;
567  int index = l * samples() + s;
568  return m_raster[index];
569  }
570 
571 
581  int TiffImporter::getGray(int pixel) const {
582  return convertRgbToGray(pixel);
583  }
584 
585 
593  int TiffImporter::getRed(int pixel) const {
594  return TIFFGetR(pixel);
595  }
596 
597 
605  int TiffImporter::getGreen(int pixel) const {
606  return TIFFGetG(pixel);
607  }
608 
609 
617  int TiffImporter::getBlue(int pixel) const {
618  return TIFFGetB(pixel);
619  }
620 
621 
629  int TiffImporter::getAlpha(int pixel) const {
630  return TIFFGetA(pixel);
631  }
632 };
633 
static Isis::Projection * Create(Isis::Pvl &label, bool allowDefaults=false)
This method returns a pointer to a Projection object.
virtual ~TiffImporter()
Destruct the importer.
virtual int convertRgbToGray(int pixel) const
Convert the current pixel, taken from an RGB/A image, and blend its RGB components into a single gray...
bool hasKeyword(const QString &name) const
Check to see if a keyword exists.
PvlGroupIterator findGroup(const QString &name, PvlGroupIterator beg, PvlGroupIterator end)
Find a group with the specified name, within these indexes.
Definition: PvlObject.h:141
virtual PvlGroup convertProjection() const
Convert any projection information associated with the input image to an ISIS Mapping group in PVL fo...
File name manipulation and expansion.
Definition: FileName.h:116
int samples() const
The sample dimension (width) of the output image.
uint16 m_photo
The enumerated photometric interpretation of the input image.
Definition: TiffImporter.h:92
const double PI
The mathematical constant PI.
Definition: Constants.h:56
TIFF * m_image
LibTIFF representation of the input image.
Definition: TiffImporter.h:86
uint16 m_samplesPerPixel
The number of "samples" (bands in Isis terms) in the input image.
Definition: TiffImporter.h:95
Base class for Map TProjections.
Definition: TProjection.h:182
void setDefaultBands()
Set the number of bands to be created for the output cube based on the number of color channels in th...
virtual int getPixel(int s, int l) const
Returns a representation of a pixel for the input format that can then be broken down into specific g...
void addGroup(const Isis::PvlGroup &group)
Add a group to the object.
Definition: PvlObject.h:198
uint32 * m_raster
Buffer holding the raw TIFF image in memory.
Definition: TiffImporter.h:89
GTIF * m_geotiff
GeoTiff hanele.
Definition: TiffImporter.h:98
QString toString(bool boolToConvert)
Global function to convert a boolean to a string.
Definition: IString.cpp:226
virtual int getAlpha(int pixel) const
Retrieves the alpha component of the given pixel.
Allows applications to translate simple text files.
This error is for when a programmer made an API call that was illegal.
Definition: IException.h:162
Pvl upperLeftXY(const Pvl &inLab) const
Convert the Tiff Tiepoint tag data to Upper Left X & Y values for the ISIS cube label mapping group...
int lines() const
The line dimension (height) of the output image.
Pvl resolution(const Pvl &inLab) const
Convert the Tiff PixelScale tag data to a singe resolution for the ISIS cube label mapping group...
virtual bool isRgb() const
Tests to see if the input image is neither grayscale nor has more than three samples per pixel...
Pvl gdalItems(const Pvl &outPvl) const
Convert items in the GDAL tag to the ISIS mapping group.
Contains multiple PvlContainers.
Definition: PvlGroup.h:57
#define _FILEINFO_
Macro for the filename and line number.
Definition: IException.h:40
void setSamples(int s)
Set the sample dimension (width) of the output image.
A type of error that could only have occurred due to a mistake on the user&#39;s part (e...
Definition: IException.h:142
A single keyword-value pair.
Definition: PvlKeyword.h:98
double LocalRadius(double lat) const
This method returns the local radius in meters at the specified latitude position.
QString expanded() const
Returns a QString of the full file name including the file path, excluding the attributes.
Definition: FileName.cpp:212
void setLines(int l)
Set the line dimension (height) of the output image.
TiffImporter(FileName inputName)
Construct the importer.
Container for cube-like labels.
Definition: Pvl.h:135
virtual int getBlue(int pixel) const
Retrieves the blue component of the given pixel.
Defines an angle and provides unit conversions.
Definition: Angle.h:62
virtual int getRed(int pixel) const
Retrieves the red component of the given pixel.
virtual int getGreen(int pixel) const
Retrieves the green component of the given pixel.
Isis exception class.
Definition: IException.h:107
Namespace for ISIS/Bullet specific routines.
Definition: Apollo.h:31
void Auto(Pvl &outputLabel)
Automatically translate all the output names found in the translation table If a output name does not...
int samplesPerPixel() const
The number of "samples" (bands in Isis terms) per pixel in the input image.
virtual void updateRawBuffer(int line, int band) const
Does nothing as LibTIFF reads the entire input image into memory, and therefore does not need to be u...
Imports images with standard formats into Isis as cubes.
Definition: ImageImporter.h:55
virtual bool isArgb() const
Tests to see if the input image is not grayscale and has more than three samples per pixel...
virtual bool isGrayscale() const
Tests to see if the input image has a "min is white" or "min is black" photometric interpretation...
bool fileExists() const
Returns true if the file exists; false otherwise.
Definition: FileName.cpp:465
virtual int getGray(int pixel) const
Retrieves the gray component of the given pixel.
virtual double TrueScaleLatitude() const
This method returns the latitude of true scale.
void deleteKeyword(const QString &name)
Remove a specified keyword.