All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Raster.cpp
Go to the documentation of this file.
1 /* Copyright (C) 2001-2009 National Institute For Space Research (INPE) - Brazil.
2 
3  This file is part of the TerraLib - a Framework for building GIS enabled applications.
4 
5  TerraLib is free software: you can redistribute it and/or modify
6  it under the terms of the GNU Lesser General Public License as published by
7  the Free Software Foundation, either version 3 of the License,
8  or (at your option) any later version.
9 
10  TerraLib is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU Lesser General Public License for more details.
14 
15  You should have received a copy of the GNU Lesser General Public License
16  along with TerraLib. See COPYING. If not, write to
17  TerraLib Team at <terralib-team@terralib.org>.
18  */
19 
20 /*!
21  \file terralib/gdal/Raster.cpp
22 
23  \brief This is a class that represents a GDAL Raster.
24  */
25 
26 // TerraLib
27 #include "../common/STLUtils.h"
28 #include "../common/StringUtils.h"
29 #include "../common/Translator.h"
30 #include "../datatype/Enums.h"
31 #include "../datatype/SimpleData.h"
32 #include "../geometry/Coord2D.h"
33 #include "../geometry/Envelope.h"
34 #include "../raster/Grid.h"
35 #include "../raster/RasterProperty.h"
36 #include "../raster/RasterFactory.h"
37 #include "../raster/Utils.h"
38 #include "../raster/Reprojection.h"
39 #include "../srs/Converter.h"
40 #include "Band.h"
41 #include "Exception.h"
42 #include "Raster.h"
43 #include "Utils.h"
44 
45 
46 // STL
47 #include <cassert>
48 #include <limits>
49 #include <stdint.h>
50 #include <map>
51 
52 // GDAL
53 #include <gdal_priv.h>
54 #include <ogr_spatialref.h>
55 
56 // Boost
57 #include <boost/lexical_cast.hpp>
58 
60  : te::rst::Raster(0),
61  m_gdataset(0),
62  m_deleter( 0 )
63 {
64 }
65 
67  : te::rst::Raster(0, p),
68  m_gdataset(0),
69  m_deleter( 0 )
70 {
71  GDALAllRegister();
72 
73  m_myURI = rinfo;
74 
78 
80 
81  if(m_gdataset == 0)
82  throw Exception(TR_GDAL("Data file can not be accessed."));
83 
85 
86  GetBands(this, m_bands);
87 }
88 
90  const std::vector<te::rst::BandProperty*>& bprops,
91  const std::map<std::string, std::string>& optParams,
93  : te::rst::Raster(grid, p),
94  m_deleter( 0 )
95 {
96  create(grid, bprops, optParams, 0, 0);
97 }
98 
99 // te::gdal::Raster::Raster(GDALDataset* gdataset, te::common::AccessPolicy p)
100 // : te::rst::Raster(0, p),
101 // m_gdataset(gdataset)
102 // {
103 // m_grid = GetGrid(m_gdataset);
104 //
105 // GetBands(this, m_bands);
106 //
107 // m_name = m_gdataset->GetDescription();
108 // }
109 
111  : te::rst::Raster(rhs),
112  m_gdataset(0),
113  m_deleter( 0 )
114 {
115  if(rhs.m_gdataset)
116  {
117 
118 
119  GDALDriver* driverPtr = rhs.m_gdataset->GetDriver();
120 
121  char** papszOptions = 0;
122 
123  m_gdataset = driverPtr->CreateCopy(rhs.m_gdataset->GetDescription(),
124  rhs.m_gdataset, 1, papszOptions,
125  NULL, NULL);
126 
127  m_myURI = m_gdataset->GetDescription();
128 
131 
132  GDALFlushCache(m_gdataset);
133 
135 
136  GetBands(this, m_bands);
137  }
138 }
139 
141 {
142  te::common::FreeContents(m_bands);
143 
144  if (m_gdataset)
145  {
146  std::string driverName = GetDriverName(m_gdataset->GetDescription());
147 
148  if ((driverName == "PNG" || driverName == "JPEG") &&
149  (m_policy == te::common::WAccess || m_policy == te::common::RWAccess))
150  {
151  char** papszOptions = 0;
152 
153  GDALDriver* driverPtr = GetGDALDriverManager()->GetDriverByName(driverName.c_str());
154 
155  GDALDataset* poDataset = driverPtr->CreateCopy(m_gdataset->GetDescription(),
156  m_gdataset, 0, papszOptions,
157  NULL, NULL);
158 
159  GDALClose(poDataset);
160  }
161 
162  GDALClose(m_gdataset);
163  }
164 
165  if(m_deleter)
166  {
167  // deleting who?
168  m_deleter = 0;
169  }
170 }
171 
172 void te::gdal::Raster::open(const std::map<std::string, std::string>& rinfo, te::common::AccessPolicy p)
173 {
174  std::map<std::string, std::string>::const_iterator it = rinfo.find("URI");
175 
176 // if URI is not specified, let's look for SOURCE
177  if(it == rinfo.end())
178  {
179  it = rinfo.find("SOURCE");
180 
181  if(it == rinfo.end())
182  throw Exception(TR_GDAL("At least the URI or SOURCE parameter must be informed!"));
183  }
184 
185  m_myURI = it->second;
186 
187  m_dsUseCounterPtr.reset( new DataSetUseCounter( GetParentDataSetName( m_myURI ),
190 
191  m_gdataset = GetRasterHandle(it->second, p);
192 
193  if(m_gdataset == 0)
194  throw Exception(TR_GDAL("Data file can not be accessed."));
195 
196  m_grid = GetGrid(m_gdataset);
197 
198  m_policy = p;
199 
200  GetBands(this, m_bands);
201 
202  m_name = m_gdataset->GetDescription();
203 }
204 
205 std::map<std::string, std::string> te::gdal::Raster::getInfo() const
206 {
207  return std::map<std::string, std::string>();
208 }
209 
211 {
212  return m_bands.size();
213 }
214 
215 int te::gdal::Raster::getBandDataType(std::size_t i) const
216 {
217  assert(i < m_bands.size());
218 
219  return m_bands[i]->getProperty()->getType();
220 }
221 
222 const te::rst::Band* te::gdal::Raster::getBand(std::size_t i) const
223 {
224  assert(i < m_bands.size());
225 
226  return m_bands[i];
227 }
228 
230 {
231  assert(i < m_bands.size());
232 
233  return m_bands[i];
234 }
235 
236 const te::rst::Band& te::gdal::Raster::operator[](std::size_t i) const
237 {
238  assert(i < m_bands.size());
239 
240  return *m_bands[i];
241 }
242 
244 {
245  assert(i < m_bands.size());
246 
247  return *m_bands[i];
248 }
249 
251 {
252  return m_gdataset;
253 }
254 
256 {
257  return new Raster(*this);
258 }
259 
261 {
263 
264  for (std::size_t b = 0; b < rhs.getNumberOfBands(); b++)
265  static_cast<te::gdal::Band*>(m_bands[b])->operator=(*static_cast<te::gdal::Band*>(rhs.m_bands[b]));
266 
267  return *this;
268 }
269 
270 te::rst::Raster* te::gdal::Raster::resample(int method, int scale, const std::map<std::string, std::string>& rinfo)
271 {
272  assert(scale != 0);
273 
274  if (!(scale < 0 && method == 3))
275  return te::rst::Raster::resample(method, scale, rinfo);
276 
277 // create output parameters and raster
278  te::rst::Grid* grid = new te::rst::Grid(*getResampledGrid(scale));
279 
280  std::vector<te::rst::BandProperty*> bands;
281 
282  for (std::size_t b = 0; b < getNumberOfBands(); b++)
283  bands.push_back(new te::rst::BandProperty(*(getBand(b)->getProperty())));
284 
285  te::rst::Raster* rout = te::rst::RasterFactory::make(grid, bands, rinfo);
286 
287  int overviewScale[1] = { -scale };
288 
289  GDALDataset* inds = static_cast<te::gdal::Raster*>(this)->getGDALDataset();
290 
291  GDALDataset* outds = static_cast<te::gdal::Raster*>(rout)->getGDALDataset();
292 
293  int overviewIndex = -1;
294  for (int ov = 0; ov < inds->GetRasterBand(1)->GetOverviewCount(); ov++)
295  if (inds->GetRasterBand(1)->GetOverview(ov)->GetXSize() == outds->GetRasterBand(1)->GetXSize())
296  {
297  overviewIndex = ov;
298  ov = inds->GetRasterBand(1)->GetOverviewCount();
299  }
300 
301  if (overviewIndex == -1)
302  {
303  inds->BuildOverviews("CUBIC", 1, overviewScale, 0, NULL, GDALDummyProgress, NULL);
304 
305  overviewIndex = inds->GetRasterBand(1)->GetOverviewCount() - 1;
306  }
307 
308  GByte* buffer = (GByte*) malloc(outds->GetRasterXSize() * outds->GetRasterYSize() * sizeof(GByte*));
309 
310  double geoT[6];
311  outds->GetGeoTransform(geoT);
312  outds->SetGeoTransform(geoT);
313 
314  for (int b = 0; b < inds->GetRasterCount(); b++)
315  {
316  GDALRasterBand* outband = outds->GetRasterBand(b + 1);
317 
318  GDALRasterBand* inband = inds->GetRasterBand(b + 1)->GetOverview(overviewIndex);
319 
320  inband->RasterIO(GF_Read, 0, 0, inband->GetXSize(), inband->GetYSize(),
321  buffer, inband->GetXSize(), inband->GetYSize(), GDT_Byte, 0, 0);
322 
323  outband->RasterIO(GF_Write, 0, 0, inband->GetXSize(), inband->GetYSize(),
324  buffer, inband->GetXSize(), inband->GetYSize(), GDT_Byte, 0, 0);
325  }
326 
327  return rout;
328 }
329 
330 te::rst::Raster* te::gdal::Raster::transform(int srid, double llx, double lly, double urx, double ury, double resx, double resy, const std::map<std::string, std::string>& rinfo, int m) const
331 {
332 // if raster out is forced to be on memory, use other implementation
333  std::map<std::string, std::string>::const_iterator it = rinfo.find("USE_TERRALIB_REPROJECTION");
334 
335  if((it != rinfo.end()) &&
336  (te::common::Convert2UCase(it->second) == "TRUE"))
337  {
338  std::map<std::string, std::string> irinfo(rinfo);
339  std::map<std::string, std::string>::iterator iit = irinfo.find("USE_TERRALIB_REPROJECTION");
340  irinfo.erase(iit);
341 
342  return te::rst::Reproject(this, srid, llx, lly, urx, ury, resx, resy, irinfo, m);
343  }
344 
345 // otherwise, use GDAL Warp function
346  if (srid == getSRID())
347  return 0;
348 
349  if (!te::gdal::RecognizesSRID(srid))
350  throw Exception(TR_GDAL("Output SRID not recognized! Expecting a EPSG SRS id."));
351 
352  unsigned int ncols = getNumberOfColumns();
353  unsigned int nrows = getNumberOfRows();
354 
355  te::gm::Envelope* roi = new te::gm::Envelope(llx, lly, urx, ury);
356  if (!roi->isValid())
357  {
358  delete roi;
359 
360  roi = 0;
361  }
362  else
363  {
364  ncols = static_cast<unsigned int>((urx-llx)/getResolutionX())+1;
365 
366  nrows = static_cast<unsigned int>((ury-lly)/getResolutionY())+1;
367  }
368 
369  te::gm::Envelope* env = this->getExtent(srid, roi);
370  delete roi;
371 
372  if (resx == 0 || resy == 0) // maintain the same number of pixels
373  {
374  resx = env->getWidth()/ncols;
375 
376  resy = env->getHeight()/nrows;
377  }
378  else
379  {
380  ncols = static_cast<unsigned int>(env->getWidth()/resx) + 1;
381 
382  nrows = static_cast<unsigned int>(env->getHeight()/resy) + 1;
383  }
384 
385  te::rst::Grid* g = new te::rst::Grid(ncols, nrows, resx, resy, env, srid);
386 
387  // copy the band definitions
388  std::vector<te::rst::BandProperty*> bands;
389  for (unsigned int b=0; b<this->getNumberOfBands(); ++b)
390  {
391  te::rst::BandProperty* bb = new te::rst::BandProperty(*this->getBand(b)->getProperty());
392 
393  bands.push_back(bb);
394  }
395 
396 // create output raster
397  te::rst::Raster* rout = te::rst::RasterFactory::make(g, bands, rinfo);
398 
399  if (te::gdal::ReprojectRaster(this, rout))
400  {
401  delete rout;
402 
404  }
405 
406  delete rout;
407 
408  return 0;
409 }
410 
412 {
413  te::gdal::ReprojectRaster(this, outRaster);
414 }
415 
417  const std::vector<te::rst::BandProperty*> bands,
418  const std::map<std::string, std::string>& rinfo,
419  void* h, void (*deleter)(void*))
420 {
421  m_grid = g;
422 
423  m_deleter = deleter;
424 
425 // always assume that a created raster needs to be written
426  m_policy = te::common::RWAccess;
427 
428  if (h)
429  {
430  intptr_t buffaddress = (intptr_t) h;
431 
432  std::string memraster = "MEM:::DATAPOINTER=";
433  memraster += boost::lexical_cast<std::string>(buffaddress);
434  memraster += ",PIXELS=";
435  memraster += te::common::Convert2String(m_grid->getNumberOfColumns());
436  memraster += ",LINES=";
437  memraster += te::common::Convert2String(m_grid->getNumberOfRows());
438  memraster += ",BANDS=";
439  memraster += boost::lexical_cast<std::string>(bands.size());
440  memraster += ",DATATYPE=";
441  memraster += GDALGetDataTypeName(GetGDALDataType(bands[0]->getType()));
442 
443  m_gdataset = GetRasterHandle(memraster.c_str(), m_policy);
444  }
445  else
446  {
447  std::map<std::string, std::string>::const_iterator it = rinfo.find("URI");
448  if(it == rinfo.end())
449  {
450  it = rinfo.find("SOURCE");
451 
452  if(it == rinfo.end())
453  throw Exception(TR_GDAL("At least the URI or SOURCE parameter must be informed!"));
454  }
455 
456  m_myURI = it->second;
457 
458  m_dsUseCounterPtr.reset( new DataSetUseCounter( m_myURI, DataSetsManager::SingleAccessType ) );
459 
460  m_gdataset = te::gdal::CreateRaster(g, bands, rinfo);
461 
463 
464  if (!m_gdataset)
465  {
466  delete g;
467  g = 0;
468 
469  std::string mess = TR_GDAL("Raster couldn't be created:");
470  mess += m_name;
471  throw Exception(mess);
472  }
473 
474  GetBands(this, m_bands);
475  }
476 }
Raster & operator=(const Raster &rhs)
Definition: Raster.cpp:260
bool isValid() const
It tells if the rectangle is valid or not.
Definition: Envelope.h:438
bool RecognizesSRID(unsigned int srid)
It returns true if GDAL recognizes the given SRS id.
Definition: Utils.cpp:573
int getBandDataType(std::size_t i) const
Returns the data type in a particular band (or dimension).
Definition: Raster.cpp:215
double getWidth() const
It returns the envelope width.
Definition: Envelope.h:443
GDALDataType GetGDALDataType(int tet)
It translates a TerraLib DataType to a GDAL DataType.
Definition: Utils.h:80
This class represents Raster data.
Definition: Raster.h:59
void FreeContents(boost::unordered_map< K, V * > &m)
This function can be applied to a map of pointers. It will delete each pointer in the map...
Definition: BoostUtils.h:55
void GetBands(te::gdal::Raster *rst, std::vector< te::gdal::Band * > &bands)
Gets the list of bands from a GDAL dataset.
Definition: Utils.cpp:297
GDALDataset * CreateRaster(te::rst::Grid *g, const std::vector< te::rst::BandProperty * > &bands, const std::map< std::string, std::string > &optParams)
Creates a raster data using GDAL.
Definition: Utils.cpp:496
It gives access to values in one band (dimension) of a raster.
std::string GetParentDataSetName(const std::string &subDataSetName)
It returns the parent dataset name from a Sub DataSet name.
Definition: Utils.cpp:749
static Raster * make()
It creates and returns an empty raster with default raster driver.
std::string Convert2UCase(const std::string &value)
It converts a string to upper case.
Definition: StringUtils.h:163
Grid * m_grid
The spatial support for raster data.
Definition: Raster.h:595
double getHeight() const
It returns the envelope height.
Definition: Envelope.h:448
GDAL data set use counter.
GDALDataset * GetRasterHandle(std::string strAccessInfo, te::common::AccessPolicy policy=te::common::RAccess)
Get a handle to a raster file.
Definition: Utils.cpp:507
AccessPolicy
Supported data access policies (can be used as bitfield).
Definition: Enums.h:40
std::string m_myURI
This instance URI;.
Definition: Raster.h:144
te::rst::Raster * resample(int method, int scale, const std::map< std::string, std::string > &rinfo)
Resample raster.
Definition: Raster.cpp:270
A raster band description.
Definition: Band.h:63
A rectified grid is the spatial support for raster data.
Definition: Grid.h:55
std::map< std::string, std::string > getInfo() const
It returns additional information about the raster.
Definition: Raster.cpp:205
~Raster()
Virtual destructor.
Definition: Raster.cpp:140
std::auto_ptr< DataSetUseCounter > m_dsUseCounterPtr
Dataset use counter pointer.
Definition: Raster.h:145
std::vector< Band * > m_bands
The vector of available bands in the raster.
Definition: Raster.h:142
const te::rst::Band & operator[](std::size_t i) const
Access band in i position.
Definition: Raster.cpp:236
GDALDataset * m_gdataset
Gdal data set handler.
Definition: Raster.h:141
te::rst::Grid * GetGrid(GDALDataset *gds)
Gets the grid definition from a GDAL dataset.
Definition: Utils.cpp:102
bool IsSubDataSet(const std::string &uri)
Returns true if the given URI is related to a sub-dataset.
Definition: Utils.cpp:726
An exception class for the GDAL module.
This class represents raster band description.
Definition: Band.h:64
TERASTEREXPORT te::rst::Raster * Reproject(te::rst::Raster const *const rin, int srid, const std::map< std::string, std::string > &routinfo, int m=te::rst::Interpolator::NearestNeighbor)
Reprojects a raster to another SRS.
std::string Convert2String(boost::int16_t value)
It converts a short integer value to a string.
Definition: StringUtils.h:51
virtual Raster & operator=(const Raster &rhs)
Assignment operator.
Definition: Raster.cpp:374
void open(const std::map< std::string, std::string > &rinfo, te::common::AccessPolicy p=te::common::RAccess)
Opens a raster.
Definition: Raster.cpp:172
A base class for values that can be retrieved from the data access module.
Definition: AbstractData.h:57
A raster band description.
Definition: BandProperty.h:61
static Raster * open(const std::map< std::string, std::string > &rinfo, te::common::AccessPolicy p=te::common::RAccess)
It opens a raster with the given parameters and default raster driver.
This is a class that represents a GDAL Raster.
const te::rst::Band * getBand(std::size_t i) const
Returns the raster i-th band.
Definition: Raster.cpp:222
Utilitary functions to access GDAL and match some of its concepts to TerraLib concepts.
bool ReprojectRaster(te::rst::Raster const *const rin, te::rst::Raster *rout)
Reprojects a raster to another SRS.
Definition: Utils.cpp:584
te::common::AccessPolicy m_policy
The access policy, can be te::common::{NoAccess, RAccess, RWAccess, WAccess}.
Definition: Raster.h:596
An abstract class for raster data strucutures.
Definition: Raster.h:70
virtual Raster * resample(int method, unsigned int drow, unsigned int dcolumn, unsigned int height, unsigned int width, unsigned int newheight, unsigned int newwidth, const std::map< std::string, std::string > &rinfo)
Resample a subset of the raster, given a box.
Definition: Raster.cpp:482
std::size_t getNumberOfBands() const
Returns the number of bands (dimension of cells attribute values) in the raster.
Definition: Raster.cpp:210
GDALDataset * getGDALDataset() const
Returns the raster GDAL handler.
Definition: Raster.cpp:250
void create(te::rst::Grid *g, const std::vector< te::rst::BandProperty * > bands, const std::map< std::string, std::string > &rinfo, void *h, void(*deleter)(void *))
Definition: Raster.cpp:416
std::string GetDriverName(const std::string &dsName)
It returns the GDAL driver name associated to a data source name.
Definition: Utils.cpp:633
An Envelope defines a 2D rectangular region.
Definition: Envelope.h:51
te::dt::AbstractData * clone() const
It returns a clone of this object.
Definition: Raster.cpp:255
#define TR_GDAL(message)
It marks a string in order to get translated. This is a special mark used in the Vector Geometry modu...
Definition: Config.h:64
te::rst::Raster * transform(int srid, double llx, double lly, double urx, double ury, double resx, double resy, const std::map< std::string, std::string > &rinfo, int m=0) const
Definition: Raster.cpp:330