openModeller  Version 1.5.0
GdalRaster.cpp
Go to the documentation of this file.
1 
34 #include <openmodeller/Log.hh>
37 
38 #include <gdal_version.h>
39 #include <gdal.h>
40 #include <gdal_priv.h>
41 #include <cpl_string.h>
42 #include <gdalwarper.h>
43 
44 #include <string.h>
45 
46 using std::string;
47 using std::vector;
48 
49 #include <utility>
50 using std::pair;
51 
52 #ifdef MPI_FOUND
53 #include "mpi.h"
54 #endif
55 
57 {
58  char const *GDalDriverName;
59  GDALDataType dataType;
60  bool hasMeta;
61 };
62 
64 {
65  // Floating GeoTiff
66  { "GTiff",
67  (sizeof(Scalar) == 4) ? GDT_Float32 : GDT_Float64,
68  true },
69  // Greyscale GeoTiff scaled 0-254
70  { "GTiff",
71  GDT_Byte,
72  true },
73  // Greyscale GeoTiff scaled 0-100
74  { "GTiff",
75  GDT_Byte,
76  true },
77  // Greyscale BMP
78  { "BMP",
79  GDT_Byte,
80  false },
81  // Floating HFA (Erdas Imagine Format)
82  { "HFA",
83  GDT_Float32,
84  true },
85  // Byte HFA (Erdas Imagine Format scaled 0-100)
86  { "HFA",
87  GDT_Byte,
88  true },
89  // Byte ASC (Arc/Info ASCII Grid Format scaled 0-100).
90  // The GDAL code here should be AAIGrid, but this driver does not support the Create
91  // method, so the trick is to create as HFA and then translate to AAIGrid
92  { "HFA",
93  GDT_Byte,
94  true },
95  // Floating ASC (Arc/Info ASCII Grid floating point format).
96  // The GDAL code here should be AAIGrid, but this driver does not support the Create
97  // method, so the trick is to create as TIF and then translate to AAIGrid
98  { "GTiff",
99  (sizeof(Scalar) == 4) ? GDT_Float32 : GDT_Float64,
100  true },
101 };
102 
103 static const GDALDataType f_type = (sizeof(Scalar) == 4) ? GDT_Float32 : GDT_Float64;
104 
105 #ifdef MPI_FOUND
106  int rank = 0;
107 #endif
108 
109 /****************************************************************/
110 /************************** Raster Gdal *************************/
111 
112 /*********************/
113 /*** create Raster ***/
114 void
115 GdalRaster::createRaster( const string& file, int categ )
116 {
117  f_file = file;
118  f_scalefactor = 1.0;
119 
120  // Opens read only and init the class attributes.
121  initGdal();
122  open( 'r' );
123 
124  // set categorical status. It's not stored as part of
125  // the gdal file's header.
126  f_hdr.categ = categ;
127 }
128 
129 #ifdef MPI_FOUND
130 void
131 GdalRaster::createRaster( const string& output_file, const string& file, const MapFormat& format)
132 {
133  MPI_Comm_rank(MPI_COMM_WORLD, &rank);
134 
135  f_file = file;
136 
137  // will be utilized by MPI
138  f_output_file = output_file;
139 
140  Scalar nv;
141 
142  switch( format.getFormat() )
143  {
144  case MapFormat::GreyBMP:
145  f_scalefactor = 255.0;
146  nv = 0.0;
147  Log::instance()->debug( "GdalRaster format set to MapFormat::GreyBMP:\n" );
148  break;
149  case MapFormat::GreyTiff:
150  f_scalefactor = 254.0;
151  nv = 255.0;
152  Log::instance()->debug( "GdalRaster format set to MapFormat::GreyTiff:\n" );
153  break;
155  f_scalefactor = 100.0;
156  nv = 127.0; //represented as 7bit so cant use 254
157  Log::instance()->debug( "GdalRaster format set to MapFormat::GreyTiff100:\n" );
158  break;
160  f_scalefactor = 1.0;
161  nv = -1.0;
162  Log::instance()->debug( "GdalRaster format set to MapFormat::FloatingTiff:\n" );
163  break;
165  f_scalefactor = 1.0;
166  nv = -1.0;
167  Log::instance()->debug( "GdalRaster format set to MapFormat::FloatingHFA:\n" );
168  break;
169  case MapFormat::ByteHFA:
170  f_scalefactor = 100;
171  nv = 101;
172  Log::instance()->debug( "GdalRaster format set to MapFormat::ByteHFA:\n" );
173  break;
174  case MapFormat::ByteASC:
175  f_scalefactor = 100;
176  nv = 101;
177  Log::instance()->debug( "GdalRaster format set to MapFormat::ByteASC:\n" );
178  break;
180  f_scalefactor = 1.0;
181  nv = -9999;
182  Log::instance()->debug( "GdalRaster format set to MapFormat::FloatingASC:\n" );
183  break;
184  default:
185  Log::instance()->error( "Unsupported output format.\n" );
186  throw InvalidParameterException( "Unsupported output format" );
187  }
188 
189  f_hdr = Header( format.getWidth(),
190  format.getHeight(),
191  format.getXMin(),
192  format.getYMin(),
193  format.getXMax(),
194  format.getYMax(),
195  nv,
196  1,
197  0 );
198 
199  f_hdr.setProj( format.getProjection() );
200 
201  // Create a new file in disk.
202  initGdal();
203  create( format.getFormat() );
204 }
205 
206 #else
207 void
208 GdalRaster::createRaster( const string& file, const MapFormat& format)
209 {
210  f_file = file;
211 
212  Scalar nv;
213 
214  switch( format.getFormat() )
215  {
216  case MapFormat::GreyBMP:
217  f_scalefactor = 255.0;
218  nv = 0.0;
219  Log::instance()->debug( "GdalRaster format set to MapFormat::GreyBMP:\n" );
220  break;
221  case MapFormat::GreyTiff:
222  f_scalefactor = 254.0;
223  nv = 255.0;
224  Log::instance()->debug( "GdalRaster format set to MapFormat::GreyTiff:\n" );
225  break;
227  f_scalefactor = 100.0;
228  nv = 127.0; //represented as 7bit so cant use 254
229  Log::instance()->debug( "GdalRaster format set to MapFormat::GreyTiff100:\n" );
230  break;
232  f_scalefactor = 1.0;
233  nv = -1.0;
234  Log::instance()->debug( "GdalRaster format set to MapFormat::FloatingTiff:\n" );
235  break;
237  f_scalefactor = 1.0;
238  nv = -1.0;
239  Log::instance()->debug( "GdalRaster format set to MapFormat::FloatingHFA:\n" );
240  break;
241  case MapFormat::ByteHFA:
242  f_scalefactor = 100;
243  nv = 101;
244  Log::instance()->debug( "GdalRaster format set to MapFormat::ByteHFA:\n" );
245  break;
246  case MapFormat::ByteASC:
247  f_scalefactor = 100;
248  nv = 101;
249  Log::instance()->debug( "GdalRaster format set to MapFormat::ByteASC:\n" );
250  break;
252  f_scalefactor = 1.0;
253  nv = -9999;
254  Log::instance()->debug( "GdalRaster format set to MapFormat::FloatingASC:\n" );
255  break;
256  default:
257  Log::instance()->error( "Unsupported output format.\n" );
258  throw InvalidParameterException( "Unsupported output format" );
259  }
260 
261  f_hdr = Header( format.getWidth(),
262  format.getHeight(),
263  format.getXMin(),
264  format.getYMin(),
265  format.getXMax(),
266  format.getYMax(),
267  nv,
268  1,
269  0 );
270 
271  f_hdr.setProj( format.getProjection() );
272 
273  // Create a new file in disk.
274  initGdal();
275  create( format.getFormat() );
276 }
277 #endif
278 
279 /*****************/
280 /*** destructor ***/
282 {
283 #ifdef MPI_FOUND
284  if (((rank != 0) && (strcmp (f_file.c_str(), f_output_file.c_str()) != 0)) || (rank == 0)){
285 #endif
286  // Save the last line read, if needed.
287  saveRow();
288 
289  if ( f_data ) {
290 
291  delete[] f_data;
292  }
293 
294  GDALClose( f_ds );
295 #ifdef MPI_FOUND
296  }
297 #endif
298 }
299 
300 
301 /************/
302 /*** read ***/
303 void
304 GdalRaster::read( Scalar *buf, int frow, int nrow )
305 {
306  // Header's data
307  int nband = f_hdr.nband;
308  int size = f_size * nrow;
309 
310  // Read each band
311  for ( int i = 1; i <= nband; i++, buf += size ) {
312 
313  // Gets the i-th band.
314  GDALRasterBand *band = f_ds->GetRasterBand( i );
315 
316  // Fill 'buf' with new data
317  int ret = band->RasterIO( GF_Read, 0, frow, f_size, nrow, buf, f_size, nrow, f_type, 0, 0 );
318 
319  if ( ret == CE_Failure ) {
320 
321  // Fill 'buf' with nodata
322  for ( int j = 0 ; j < f_size; j++ ) {
323 
324  buf[j] = f_hdr.noval;
325  }
326  }
327  }
328 }
329 
330 
331 /*************/
332 /*** write ***/
333 void
334 GdalRaster::write( Scalar *buf, int frow, int nrow )
335 {
336  // Header's data.
337  int nband = f_hdr.nband;
338  int size = f_size * nrow;
339 
340  // Write each band in the file.
341  for ( int i = 1; i <= nband; i++, buf += size ) {
342 
343  // Gets the i-th band.
344  GDALRasterBand *band = f_ds->GetRasterBand( i );
345 
346  // Write the buffer's data in the file.
347  int ret = band->RasterIO( GF_Write, 0, frow, f_size, nrow, buf, f_size, nrow, f_type, 0, 0 );
348 
349  if ( ret == CE_Failure )
350  {
351  Log::instance()->error( "Unable to write to file %s\n", f_file.c_str());
352  throw FileIOException( "Unable to write to file " + f_file, f_file );
353  }
354  }
355 }
356 
357 /************/
358 /*** open ***/
359 void
360 GdalRaster::open( char mode )
361 {
362  // Mode: write or read.
363  GDALAccess gmod = (mode == 'w') ? GA_Update : GA_ReadOnly;
364 
365  // Opens the file.
366  f_ds = (GDALDataset *)GDALOpenShared( f_file.c_str(), gmod );
367 
368  if ( ! f_ds ) {
369 
370  Log::instance()->error( "Unable to open file %s\n", f_file.c_str());
371  throw FileIOException( "Unable to open file " + f_file, f_file );
372  }
373 
374  // Number of bands (channels).
375  f_hdr.nband = f_ds->GetRasterCount();
376 
377  // Projection.
378  const char * projwkt = (char *)f_ds->GetProjectionRef();
379 
380  f_hdr.setProj( projwkt );
381 
382  if ( ! f_hdr.hasProj() ) {
383 
384  Log::instance()->warn( "The raster %s is not georeferenced. Assuming LatLong WGS84\n", f_file.c_str() );
386  }
387 
388  // Assumes that all bands have the same georeference
389  // characteristics, ie, the same header.
390 
391  GDALRasterBand *band = f_ds->GetRasterBand( 1 );
392 
393  int xd = f_hdr.xdim = band->GetXSize();
394  int yd = f_hdr.ydim = band->GetYSize();
395 
396  f_hdr.noval = band->GetNoDataValue();
397 
398  // Map limits.
399  double cf[6];
400  f_ds->GetGeoTransform( cf );
401  f_hdr.xmin = (Scalar) cf[0];
402  f_hdr.xmax = (Scalar) (cf[0] + xd * cf[1] + yd * cf[2]);
403  f_hdr.ymax = (Scalar) cf[3];
404  f_hdr.ymin = (Scalar) (cf[3] + xd * cf[4] + yd * cf[5]);
405 
406  //Log::instance()->debug( "Raster boundaries: xmin=%f, xmax=%f, ymin=%f, ymax=%f \n", f_hdr.xmin, f_hdr.xmax, f_hdr.ymin, f_hdr.ymax );
407 
409 
410  for ( int i=0; i<6; ++i ) {
411 
412  f_hdr.gt[i] = cf[i];
413  }
414 
415  // Minimum and maximum values.
416  f_hdr.vmin = band->GetMinimum( &f_hdr.minmax );
417 
418  if ( f_hdr.minmax ) {
419 
420  f_hdr.vmax = band->GetMaximum();
421  }
422 
423  // Assumes grid (in place of 'pixel').
424  // todo: how can I read this with GDAL?
425  f_hdr.grid = 0;
426 
427  // Create warped data set when coordinate system is different
429 
430  GDALWarpOptions *warpOptions = GDALCreateWarpOptions();
431 
432  f_warped_ds = (GDALDataset *)GDALAutoCreateWarpedVRT( f_ds, projwkt, GeoTransform::getDefaultCS(), GRA_NearestNeighbour, 0.0, warpOptions );
433  }
434 
435  // Initialize the Buffer
436  initBuffer();
437 }
438 
439 /**************/
440 /*** create ***/
441 void
442 GdalRaster::create( int format )
443 {
444  // Store format for future reference (used in method "finish")
445  f_format = format;
446 
447  GDALDriver *poDriver;
448  char **papszMetadata;
449 
450  char const *fmt = Formats[ format ].GDalDriverName;
451 
452  // Added by Tim to see if the chosen format supports the gdal create method
453  poDriver = GetGDALDriverManager()->GetDriverByName(fmt);
454 
455  if ( poDriver == NULL ) {
456 
457  std::string msg = "Unable to load GDAL driver " + string(fmt) + " for file " + f_file;
458 
459  Log::instance()->error( msg.c_str() );
460 
461  throw FileIOException( "Unable to load GDAL driver " + string(fmt), f_file );
462  }
463 
464  papszMetadata = poDriver->GetMetadata();
465 
466  if ( ! CSLFetchBoolean( papszMetadata, GDAL_DCAP_CREATE, FALSE ) ) {
467 
468  Log::instance()->error( "Driver %s, format %s does not support Create() method.\n",
469  poDriver->GetDescription(),
470  fmt );
471 
472  throw FileIOException( "Driver " + string(fmt) + " does not support Create() method", f_file );
473  }
474 
475  // Read the parameters in 'hdr' used to create the file.
476  // The other parameters come from the copied header.
477  f_hdr.nband = 1;
478 
479  // Create the file.
480  if ( format == MapFormat::FloatingHFA || format == MapFormat::ByteHFA ) {
481 
482  // Note: HFA (erdas imagine) format does not support nodata before GDAL 1.5
483  // see http://www.gdal.org/gdal_tutorial.html for options examples
484  char **papszOptions = NULL;
485 
486  papszOptions = CSLSetNameValue( papszOptions, "COMPRESS", "YES" );
487  #ifdef MPI_FOUND
488  if (rank ==0){
489  #endif
490  f_ds = poDriver->Create( f_file.c_str(),
491  f_hdr.xdim, f_hdr.ydim,
492  f_hdr.nband,
493  Formats[format].dataType,
494  papszOptions );
495  #ifdef MPI_FOUND
496  }
497  #endif
498  CSLDestroy( papszOptions );
499  }
500  //ArcMap needs a LZW compression license to read files compressed
501  //like this so you may need to comment out this code if you want
502  //to open the generated maps without having the license. Compression
503  //is enabled for now because it offers significant size reduction.
504  else if (format == MapFormat::GreyTiff100)
505  {
506  //lzw compression and represent each pixel with 7bits only
507  char **papszOptions = NULL;
508  papszOptions = CSLSetNameValue( papszOptions, "NBITS", "7" );
509  papszOptions = CSLSetNameValue( papszOptions, "COMPRESS", "LZW" );
510  #ifdef MPI_FOUND
511  if (rank ==0){
512  #endif
513  f_ds = poDriver->Create( f_file.c_str(),
514  f_hdr.xdim, f_hdr.ydim,
515  f_hdr.nband,
516  Formats[format].dataType, //data type
517  papszOptions ); //opt parameters
518  #ifdef MPI_FOUND
519  }
520  #endif
521  CSLDestroy( papszOptions );
522  }
523  //Create temporary ByteHFA file with a different name (original file name + .tmp)
524  //It will be converted to ASC in the finish method
525  else if (format==MapFormat::ByteASC)
526  {
527  std::string temp_file = f_file + ".tmp";
528 
529  #ifdef MPI_FOUND
530  if (rank ==0){
531  #endif
532  f_ds = poDriver->Create( temp_file.c_str(),
533  f_hdr.xdim, f_hdr.ydim,
534  f_hdr.nband,
535  Formats[format].dataType,
536  NULL );
537  #ifdef MPI_FOUND
538  }
539  #endif
540  }
541  //Create temporary GeoTiff file with a different name (original file name + .tmp)
542  //It will be converted to ASC in the finish method
543  else if (format==MapFormat::FloatingASC)
544  {
545  std::string temp_file = f_file + ".tmp";
546 
547  #ifdef MPI_FOUND
548  if (rank ==0){
549  #endif
550  f_ds = poDriver->Create( temp_file.c_str(),
551  f_hdr.xdim, f_hdr.ydim,
552  f_hdr.nband,
553  Formats[format].dataType,
554  NULL );
555  #ifdef MPI_FOUND
556  }
557  #endif
558  }
559  else {
560  #ifdef MPI_FOUND
561  if (rank ==0){
562  #endif
563  //uncompressed
564  f_ds = poDriver->Create( f_file.c_str(),
565  f_hdr.xdim, f_hdr.ydim,
566  f_hdr.nband,
567  Formats[format].dataType,
568  NULL );
569  #ifdef MPI_FOUND
570  }
571  #endif
572  }
573 
574  #ifdef MPI_FOUND
575  if (rank ==0) {
576  #endif
577  if ( ! f_ds ) {
578 
579  Log::instance()->warn( "Unable to create file %s.\n",f_file.c_str() );
580  throw FileIOException( "Unable to create file " + f_file, f_file );
581  }
582 
583  if ( Formats[format].hasMeta ) {
584 
585  // Metadata
586 
587  // Limits (without rotations).
588  f_ds->SetGeoTransform( f_hdr.gt );
589 
590  // Projection.
591  f_ds->SetProjection( f_hdr.proj.c_str() );
592 
593  // Sets the "nodata" value in all bands.
594  int ret = f_ds->GetRasterBand(1)->SetNoDataValue( f_hdr.noval );
595 
596  if ( ret == CE_Failure ) {
597 
598  Log::instance()->warn( "Raster %s (%s) does not support nodata value assignment. Nodata values will correspond to %f anyway, but this will not be stored as part of the raster metadata.\n", f_file.c_str(), fmt, f_hdr.noval );
599  }
600  }
601  #ifdef MPI_FOUND
602  }
603  #endif
604  // Initialize the Buffer
605  initBuffer();
606 }
607 
608 /*******************/
609 /*** init Buffer ***/
610 void
612 {
613  // Initialize the buffer.
614  f_size = f_hdr.xdim;
615 
616  if ( f_data ) {
617 
618  delete[] f_data;
619  }
620 
621  f_data = new Scalar[ f_size * f_hdr.nband ];
622 
623  f_changed = 0;
624  f_currentRow = -1;
625 }
626 
627 /*****************/
628 /*** init Gdal ***/
629 void
631 {
632  static int first = 1;
633 
634  if ( first ) {
635 
636  first = 0;
637  GDALAllRegister();
638  }
639 }
640 
641 /************/
642 /*** iput ***/
643 int
644 GdalRaster::iput( int x, int y, Scalar val )
645 {
646  // Be sure that 'y' line is in the buffer 'f_data'.
647  loadRow( y, true );
648 
649  // Put values in the first band of (x,y) position.
650  f_data[x] = val;
651 
652  // Indicates the line 'f_currentRow' has changed.
653  f_changed = 1;
654 
655  return 1;
656 }
657 
658 /************/
659 /*** iget ***/
660 int
661 GdalRaster::iget( int x, int y, Scalar *val )
662 {
663  // Be sure that 'y' line is in the buffer 'f_data'.
664  loadRow( y );
665 
666  // Get all band's values.
667  Scalar *pv = val;
668  int nband = f_hdr.nband;
669  for ( int i = 0; i < nband; i++, x += f_size ) {
670 
671  if ( (*pv++ = f_data[x]) == f_hdr.noval ) {
672 
673  return 0;
674  }
675  }
676 
677  return 1;
678 }
679 
680 /***********/
681 /*** get ***/
682 int
684 {
685  Scalar *pv = val;
686  for ( int i = 0; i < f_hdr.nband; i++ ) {
687 
688  *pv++ = f_hdr.noval;
689  }
690 
691  pair<int,int> xy = f_hdr.convertLonLat2XY( px, py );
692  int x = xy.first;
693  int y = xy.second;
694 
695  // If the point is out of range, returns 0.
696  if ( x < 0 || x >= f_hdr.xdim || y < 0 || y >= f_hdr.ydim ) {
697 
698  //Log::instance()->debug( "Raster::get() Pixel (%d,%d) is not in extent\n",x,y);
699  return 0;
700  }
701 
702  // 'iget()' detects if the coordinate has or not valid
703  // information (noval);
704  return iget( x, y, val );
705 }
706 
707 /***********/
708 /*** put ***/
709 int
711 {
712  pair<int,int> xy = f_hdr.convertLonLat2XY( px, py );
713  int x = xy.first;
714  int y = xy.second;
715 
716  if ( x < 0 || x >= f_hdr.xdim || y < 0 || y >= f_hdr.ydim ) {
717 
718  Log::instance()->warn( "Coordinate (%f, %f) corresponds to a cell (%d, %d) outside the raster boundaries. It will be ignored.\n", px, py, x, y );
719  return 0;
720  }
721 
722  return iput( x, y, f_scalefactor*val );
723 }
724 
725 /***********/
726 /*** put ***/
727 int
729 {
730  pair<int,int> xy = f_hdr.convertLonLat2XY( px, py );
731  int x = xy.first;
732  int y = xy.second;
733 
734  Scalar val = f_hdr.noval;
735 
736  if ( x < 0 || x >= f_hdr.xdim || y < 0 || y >= f_hdr.ydim ) {
737 
738  Log::instance()->warn( "Coordinate (%f, %f) corresponds to a cell (%d, %d) outside the raster boundaries. It will be ignored.\n", px, py, x, y );
739  return 0;
740  }
741 
742  return iput( x, y, val );
743 }
744 
745 /*******************/
746 /*** get Min Max ***/
747 int
749 {
750  if ( ! calcMinMax() ) {
751 
752  return 0;
753  }
754 
755  *min = f_hdr.vmin;
756 
757  *max = f_hdr.vmax;
758 
759  return 1;
760 }
761 
762 /********************/
763 /*** calc Min Max ***/
764 int
766 {
767  if ( f_hdr.minmax ) {
768 
769  return 1;
770  }
771 
772  Scalar *bands;
773  bands = new Scalar[ f_hdr.nband ];
774  Scalar *val = bands + band;
775  Scalar min=0;
776  Scalar max=0;
777 
778  bool initialized = false;
779 
780  // Scan all map values.
781  for ( int y = 0; y < f_hdr.ydim; y++ ) {
782 
783  for ( int x = 0; x < f_hdr.xdim; x++ ) {
784 
785  if ( iget( x, y, bands ) ) {
786 
787  if ( !initialized ) {
788 
789  initialized = true;
790  min = max = *val;
791  }
792 
793  if ( min > *val ) {
794 
795  min = *val;
796  }
797  else if ( max < *val ) {
798 
799  max = *val;
800  }
801  }
802  }
803  }
804 
805  delete[] bands;
806 
807  if ( ! initialized ) {
808 
809  return 0;
810  }
811 
812  // This is only logically const. Here we cast away const to cache the min/max
813  Header *f_hdrNoConst = const_cast<Header*>(&f_hdr);
814 
815  f_hdrNoConst->minmax = 1;
816  f_hdrNoConst->vmin = min;
817  f_hdrNoConst->vmax = max;
818 
819  return 1;
820 }
821 
822 /****************/
823 /*** load Row ***/
824 void
825 GdalRaster::loadRow( int row, bool writeOperation )
826 {
827  // If the line is already read, return.
828  if ( row == f_currentRow ) {
829 
830  return;
831  }
832 
833  saveRow();
834 
835  // Update f_data
836  if ( writeOperation ) {
837 
838  // Just reset f_data with nodata
839  for ( int i = 0 ; i < f_size; i++ ) {
840 
841  f_data[i] = f_hdr.noval;
842  }
843  }
844  else {
845 
846  // Read from file
847  read( f_data, row, 1 );
848  }
849 
850  f_currentRow = row;
851  f_changed = 0;
852 }
853 
854 
855 /****************/
856 /*** save Row ***/
857 void
859 {
860  if ( ! f_changed || f_currentRow < 0 ) {
861 
862  return;
863  }
864 
865  write( f_data, f_currentRow, 1 );
866 
867  f_changed = 0;
868 }
869 
870 /**************/
871 /*** finish ***/
872 void
874 {
875  // Save the last line read, if needed.
876  saveRow();
877 
879  {
880  // Temporary file name
881  std::string temp_file = f_file + ".tmp";
882 
883  // Get ArcInfo/ASC Grid driver
884  GDALDriver *hDriver;
885  hDriver = GetGDALDriverManager()->GetDriverByName("AAIGrid");
886 
887  if ( hDriver == NULL ) {
888 
889  std::string msg = "Unable to load AAIGrid GDAL driver";
890 
891  Log::instance()->error( msg.c_str() );
892  throw FileIOException( msg.c_str(), f_file );
893  }
894 
895  // Convert temporary raster to ArcInfo/ASC Grid
896  GDALDataset * new_ds = hDriver->CreateCopy( f_file.c_str(), f_ds, FALSE, NULL, NULL, NULL );
897 
898  if ( ! new_ds ) {
899 
900  Log::instance()->warn( "Unable to create raster copy %s.\n",f_file.c_str() );
901  throw FileIOException( "Unable to create raster copy " + f_file, f_file );
902  }
903 
904  // Delete temporary ByteHFA raster
905 #if GDAL_VERSION_MAJOR > 1 || ( GDAL_VERSION_MAJOR == 1 && GDAL_VERSION_MINOR >= 5 )
906 
907  delete f_ds;
908 
909  if ( GDALDriver::QuietDelete( temp_file.c_str() ) == CE_Failure )
910  {
911  Log::instance()->warn( "Could not delete temporary file %s", temp_file.c_str() );
912  }
913 #else
914  GDALDriver * temp_driver = f_ds->GetDriver();
915 
916  if ( temp_driver->Delete( temp_file.c_str() ) == CE_Failure )
917  {
918  Log::instance()->warn( "Could not delete temporary file %s", temp_file.c_str() );
919  }
920 
921  delete f_ds;
922 #endif
923 
924  f_ds = new_ds;
925  }
926 }
927 
928 /*********************/
929 /*** delete Raster ***/
930 int
932 {
933  GDALDriver * driver = f_ds->GetDriver();
934 
935  int ret = driver->Delete( f_file.c_str() );
936 
937  if ( ret == CE_Failure ) {
938 
939  return 0;
940  }
941 
942  f_ds = 0;
943 
944  return 1;
945 }
946 
947 /*****************************/
948 /*** getExtentInStandardCs ***/
949 int
951 {
952  if ( f_warped_ds == 0 ) {
953 
954  return 0;
955  }
956 
957  GDALRasterBand *band = f_warped_ds->GetRasterBand( 1 );
958 
959  int xd = band->GetXSize();
960  int yd = band->GetYSize();
961 
962  double cf[6];
963  f_warped_ds->GetGeoTransform( cf );
964 
965  *xmin = cf[0];
966  *ymin = cf[3] + xd * cf[4] + yd * cf[5];
967  *xmax = cf[0] + xd * cf[1] + yd * cf[2];
968  *ymax = cf[3];
969 
970  return 1;
971 }
int categ
Definition: Header.hh:93
GDALDataset * f_warped_ds
Definition: GdalRaster.hh:195
void warn(const char *format,...)
'Warn' level.
Definition: Log.cpp:273
Coord getYMin() const
Definition: MapFormat.cpp:305
std::string getProjection() const
Definition: MapFormat.cpp:361
GDAL_Format Formats[8]
Definition: GdalRaster.cpp:63
Scalar vmin
Definition: Header.hh:101
void finish()
Definition: GdalRaster.cpp:873
int xdim
Definition: Header.hh:72
Scalar vmax
Definition: Header.hh:102
double Scalar
Type of map values.
Definition: om_defs.hh:39
void calculateCell()
Definition: Header.cpp:130
int ydim
Definition: Header.hh:73
int nband
Definition: Header.hh:83
static const GDALDataType f_type
Definition: GdalRaster.cpp:103
static bool compareCoordSystemStrings(char const *s1, char const *s2)
Coord xmin
Definition: Header.hh:74
Coord xmax
Definition: Header.hh:76
int getExtentInStandardCs(Coord *xmin, Coord *ymin, Coord *xmax, Coord *ymax)
Definition: GdalRaster.cpp:950
static Log * instance()
Returns the instance pointer, creating the object on the first call.
Definition: Log.cpp:45
static void initGdal()
Definition: GdalRaster.cpp:630
int hasProj() const
Definition: Header.hh:65
void open(char mode)
Definition: GdalRaster.cpp:360
std::pair< int, int > convertLonLat2XY(Coord lon, Coord lat) const
Definition: Header.cpp:160
Coord getXMax() const
Definition: MapFormat.cpp:319
void saveRow()
Definition: GdalRaster.cpp:858
Scalar noval
Definition: Header.hh:82
int get(Coord x, Coord y, Scalar *val)
Definition: GdalRaster.cpp:683
Definition: Header.hh:45
int iput(int x, int y, Scalar val)
Definition: GdalRaster.cpp:644
GDALDataset * f_ds
Definition: GdalRaster.hh:179
void error(const char *format,...)
'Error' level.
Definition: Log.cpp:290
std::string proj
Definition: Header.hh:104
Coord gt[6]
Definition: Header.hh:80
Coord ymin
Definition: Header.hh:75
int getFormat() const
Definition: MapFormat.hh:97
Coord getYMax() const
Definition: MapFormat.cpp:333
Scalar f_scalefactor
Definition: Raster.hh:184
Scalar * f_data
Definition: GdalRaster.hh:181
int grid
Definition: Header.hh:86
GDALDataType dataType
Definition: GdalRaster.cpp:59
Coord ymax
Definition: Header.hh:77
int deleteRaster()
Definition: GdalRaster.cpp:931
char const * GDalDriverName
Definition: GdalRaster.cpp:58
static char const * getDefaultCS()
void read(Scalar *buf, int first_row, int num_rows)
Definition: GdalRaster.cpp:304
Coord getXMin() const
Definition: MapFormat.cpp:291
Header f_hdr
Definition: Raster.hh:192
void write(Scalar *buf, int first_row, int num_rows)
Definition: GdalRaster.cpp:334
int getWidth() const
Definition: MapFormat.cpp:245
int getHeight() const
Definition: MapFormat.cpp:256
void createRaster(const std::string &file, int categ=0)
int minmax
Definition: Header.hh:99
int put(Coord x, Coord y, Scalar val)
Definition: GdalRaster.cpp:710
void loadRow(int row, bool writeOperation=false)
Definition: GdalRaster.cpp:825
int getMinMax(Scalar *min, Scalar *max)
Definition: GdalRaster.cpp:748
int iget(int x, int y, Scalar *val)
Definition: GdalRaster.cpp:661
int f_currentRow
Definition: GdalRaster.hh:186
double Coord
Type of map coordinates.
Definition: om_defs.hh:38
void initBuffer()
Definition: GdalRaster.cpp:611
void create(int format)
Definition: GdalRaster.cpp:442
int calcMinMax(int band=0)
Definition: GdalRaster.cpp:765
void debug(const char *format,...)
'Debug' level.
Definition: Log.cpp:237
void setProj(const std::string &projection)
Definition: Header.cpp:142
int min(int v1, int v2)
Definition: rules_base.cpp:56
std::string f_file
Definition: Raster.hh:186