PostGIS  2.4.9dev-r@@SVN_REVISION@@

◆ RASTER_addBandOutDB()

Datum RASTER_addBandOutDB ( PG_FUNCTION_ARGS  )

Definition at line 546 of file rtpg_create.c.

References ovdump::band, ES_ERROR, ES_NONE, FALSE, window::gt, PG_FUNCTION_INFO_V1(), POSTGIS_RT_DEBUG, PT_END, rtrowdump::raster, RASTER_copyBand(), rt_band_new_offline(), rt_raster_add_band(), rt_raster_deserialize(), rt_raster_destroy(), rt_raster_get_geotransform_matrix(), rt_raster_get_height(), rt_raster_get_num_bands(), rt_raster_get_srid(), rt_raster_get_width(), rt_raster_is_empty(), rt_raster_new(), rt_raster_same_alignment(), rt_raster_serialize(), rt_raster_set_geotransform_matrix(), rt_raster_set_srid(), rt_util_gdal_datatype_to_pixtype(), rt_util_gdal_open(), rt_util_gdal_register_all(), rt_util_gdal_sr_auth_info(), rt_raster_serialized_t::size, SRID_UNKNOWN, and TRUE.

Referenced by RASTER_addBandRasterArray().

547 {
548  rt_pgraster *pgraster = NULL;
549  rt_pgraster *pgrtn = NULL;
550 
551  rt_raster raster = NULL;
552  rt_band band = NULL;
553  int numbands = 0;
554  int dstnband = 1; /* 1-based */
555  int appendband = FALSE;
556  char *outdbfile = NULL;
557  int *srcnband = NULL; /* 1-based */
558  int numsrcnband = 0;
559  int allbands = FALSE;
560  int hasnodata = FALSE;
561  double nodataval = 0.;
562  uint16_t width = 0;
563  uint16_t height = 0;
564  char *authname = NULL;
565  char *authcode = NULL;
566 
567  int i = 0;
568  int j = 0;
569 
570  GDALDatasetH hdsOut;
571  GDALRasterBandH hbandOut;
572  GDALDataType gdpixtype;
573 
574  rt_pixtype pt = PT_END;
575  double gt[6] = {0.};
576  double ogt[6] = {0.};
577  rt_raster _rast = NULL;
578  int aligned = 0;
579  int err = 0;
580 
581  /* destination raster */
582  if (!PG_ARGISNULL(0)) {
583  pgraster = (rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
584 
585  /* raster */
586  raster = rt_raster_deserialize(pgraster, FALSE);
587  if (!raster) {
588  PG_FREE_IF_COPY(pgraster, 0);
589  elog(ERROR, "RASTER_addBandOutDB: Could not deserialize destination raster");
590  PG_RETURN_NULL();
591  }
592 
593  POSTGIS_RT_DEBUG(4, "destination raster isn't NULL");
594  }
595 
596  /* destination band index (1) */
597  if (!PG_ARGISNULL(1))
598  dstnband = PG_GETARG_INT32(1);
599  else
600  appendband = TRUE;
601 
602  /* outdb file (2) */
603  if (PG_ARGISNULL(2)) {
604  elog(NOTICE, "Out-db raster file not provided. Returning original raster");
605  if (pgraster != NULL) {
606  rt_raster_destroy(raster);
607  PG_RETURN_POINTER(pgraster);
608  }
609  else
610  PG_RETURN_NULL();
611  }
612  else {
613  outdbfile = text_to_cstring(PG_GETARG_TEXT_P(2));
614  if (!strlen(outdbfile)) {
615  elog(NOTICE, "Out-db raster file not provided. Returning original raster");
616  if (pgraster != NULL) {
617  rt_raster_destroy(raster);
618  PG_RETURN_POINTER(pgraster);
619  }
620  else
621  PG_RETURN_NULL();
622  }
623  }
624 
625  /* outdb band index (3) */
626  if (!PG_ARGISNULL(3)) {
627  ArrayType *array;
628  Oid etype;
629  Datum *e;
630  bool *nulls;
631 
632  int16 typlen;
633  bool typbyval;
634  char typalign;
635 
636  allbands = FALSE;
637 
638  array = PG_GETARG_ARRAYTYPE_P(3);
639  etype = ARR_ELEMTYPE(array);
640  get_typlenbyvalalign(etype, &typlen, &typbyval, &typalign);
641 
642  switch (etype) {
643  case INT2OID:
644  case INT4OID:
645  break;
646  default:
647  if (pgraster != NULL) {
648  rt_raster_destroy(raster);
649  PG_FREE_IF_COPY(pgraster, 0);
650  }
651  elog(ERROR, "RASTER_addBandOutDB: Invalid data type for band indexes");
652  PG_RETURN_NULL();
653  break;
654  }
655 
656  deconstruct_array(array, etype, typlen, typbyval, typalign, &e, &nulls, &numsrcnband);
657 
658  srcnband = palloc(sizeof(int) * numsrcnband);
659  if (srcnband == NULL) {
660  if (pgraster != NULL) {
661  rt_raster_destroy(raster);
662  PG_FREE_IF_COPY(pgraster, 0);
663  }
664  elog(ERROR, "RASTER_addBandOutDB: Could not allocate memory for band indexes");
665  PG_RETURN_NULL();
666  }
667 
668  for (i = 0, j = 0; i < numsrcnband; i++) {
669  if (nulls[i]) continue;
670 
671  switch (etype) {
672  case INT2OID:
673  srcnband[j] = DatumGetInt16(e[i]);
674  break;
675  case INT4OID:
676  srcnband[j] = DatumGetInt32(e[i]);
677  break;
678  }
679  j++;
680  }
681 
682  if (j < numsrcnband) {
683  srcnband = repalloc(srcnband, sizeof(int) * j);
684  if (srcnband == NULL) {
685  if (pgraster != NULL) {
686  rt_raster_destroy(raster);
687  PG_FREE_IF_COPY(pgraster, 0);
688  }
689  elog(ERROR, "RASTER_addBandOutDB: Could not reallocate memory for band indexes");
690  PG_RETURN_NULL();
691  }
692 
693  numsrcnband = j;
694  }
695  }
696  else
697  allbands = TRUE;
698 
699  /* nodataval (4) */
700  if (!PG_ARGISNULL(4)) {
701  hasnodata = TRUE;
702  nodataval = PG_GETARG_FLOAT8(4);
703  }
704  else
705  hasnodata = FALSE;
706 
707  /* validate input */
708 
709  /* make sure dstnband is valid */
710  if (raster != NULL) {
711  numbands = rt_raster_get_num_bands(raster);
712  if (!appendband) {
713  if (dstnband < 1) {
714  elog(NOTICE, "Invalid band index %d for adding bands. Using band index 1", dstnband);
715  dstnband = 1;
716  }
717  else if (numbands > 0 && dstnband > numbands) {
718  elog(NOTICE, "Invalid band index %d for adding bands. Using band index %d", dstnband, numbands);
719  dstnband = numbands + 1;
720  }
721  }
722  else
723  dstnband = numbands + 1;
724  }
725 
726  /* open outdb raster file */
728  hdsOut = rt_util_gdal_open(outdbfile, GA_ReadOnly, 0);
729  if (hdsOut == NULL) {
730  if (pgraster != NULL) {
731  rt_raster_destroy(raster);
732  PG_FREE_IF_COPY(pgraster, 0);
733  }
734  elog(ERROR, "RASTER_addBandOutDB: Could not open out-db file with GDAL");
735  PG_RETURN_NULL();
736  }
737 
738  /* get offline raster's geotransform */
739  if (GDALGetGeoTransform(hdsOut, ogt) != CE_None) {
740  ogt[0] = 0;
741  ogt[1] = 1;
742  ogt[2] = 0;
743  ogt[3] = 0;
744  ogt[4] = 0;
745  ogt[5] = -1;
746  }
747 
748  /* raster doesn't exist, create it now */
749  if (raster == NULL) {
750  raster = rt_raster_new(GDALGetRasterXSize(hdsOut), GDALGetRasterYSize(hdsOut));
751  if (rt_raster_is_empty(raster)) {
752  elog(ERROR, "RASTER_addBandOutDB: Could not create new raster");
753  PG_RETURN_NULL();
754  }
757 
758  if (rt_util_gdal_sr_auth_info(hdsOut, &authname, &authcode) == ES_NONE) {
759  if (
760  authname != NULL &&
761  strcmp(authname, "EPSG") == 0 &&
762  authcode != NULL
763  ) {
764  rt_raster_set_srid(raster, atoi(authcode));
765  }
766  else
767  elog(INFO, "Unknown SRS auth name and code from out-db file. Defaulting SRID of new raster to %d", SRID_UNKNOWN);
768  }
769  else
770  elog(INFO, "Could not get SRS auth name and code from out-db file. Defaulting SRID of new raster to %d", SRID_UNKNOWN);
771  }
772 
773  /* some raster info */
774  width = rt_raster_get_width(raster);
775  height = rt_raster_get_height(raster);
776 
777  /* are rasters aligned? */
778  _rast = rt_raster_new(1, 1);
780  rt_raster_set_srid(_rast, rt_raster_get_srid(raster));
781  err = rt_raster_same_alignment(raster, _rast, &aligned, NULL);
782  rt_raster_destroy(_rast);
783 
784  if (err != ES_NONE) {
785  GDALClose(hdsOut);
786  if (raster != NULL)
787  rt_raster_destroy(raster);
788  if (pgraster != NULL)
789  PG_FREE_IF_COPY(pgraster, 0);
790  elog(ERROR, "RASTER_addBandOutDB: Could not test alignment of out-db file");
791  return ES_ERROR;
792  }
793  else if (!aligned)
794  elog(WARNING, "The in-db representation of the out-db raster is not aligned. Band data may be incorrect");
795 
796  numbands = GDALGetRasterCount(hdsOut);
797 
798  /* build up srcnband */
799  if (allbands) {
800  numsrcnband = numbands;
801  srcnband = palloc(sizeof(int) * numsrcnband);
802  if (srcnband == NULL) {
803  GDALClose(hdsOut);
804  if (raster != NULL)
805  rt_raster_destroy(raster);
806  if (pgraster != NULL)
807  PG_FREE_IF_COPY(pgraster, 0);
808  elog(ERROR, "RASTER_addBandOutDB: Could not allocate memory for band indexes");
809  PG_RETURN_NULL();
810  }
811 
812  for (i = 0, j = 1; i < numsrcnband; i++, j++)
813  srcnband[i] = j;
814  }
815 
816  /* check band properties and add band */
817  for (i = 0, j = dstnband - 1; i < numsrcnband; i++, j++) {
818  /* valid index? */
819  if (srcnband[i] < 1 || srcnband[i] > numbands) {
820  elog(NOTICE, "Out-db file does not have a band at index %d. Returning original raster", srcnband[i]);
821  GDALClose(hdsOut);
822  if (raster != NULL)
823  rt_raster_destroy(raster);
824  if (pgraster != NULL)
825  PG_RETURN_POINTER(pgraster);
826  else
827  PG_RETURN_NULL();
828  }
829 
830  /* get outdb band */
831  hbandOut = NULL;
832  hbandOut = GDALGetRasterBand(hdsOut, srcnband[i]);
833  if (NULL == hbandOut) {
834  GDALClose(hdsOut);
835  if (raster != NULL)
836  rt_raster_destroy(raster);
837  if (pgraster != NULL)
838  PG_FREE_IF_COPY(pgraster, 0);
839  elog(ERROR, "RASTER_addBandOutDB: Could not get band %d from GDAL dataset", srcnband[i]);
840  PG_RETURN_NULL();
841  }
842 
843  /* supported pixel type */
844  gdpixtype = GDALGetRasterDataType(hbandOut);
845  pt = rt_util_gdal_datatype_to_pixtype(gdpixtype);
846  if (pt == PT_END) {
847  elog(NOTICE, "Pixel type %s of band %d from GDAL dataset is not supported. Returning original raster", GDALGetDataTypeName(gdpixtype), srcnband[i]);
848  GDALClose(hdsOut);
849  if (raster != NULL)
850  rt_raster_destroy(raster);
851  if (pgraster != NULL)
852  PG_RETURN_POINTER(pgraster);
853  else
854  PG_RETURN_NULL();
855  }
856 
857  /* use out-db band's nodata value if nodataval not already set */
858  if (!hasnodata)
859  nodataval = GDALGetRasterNoDataValue(hbandOut, &hasnodata);
860 
861  /* add band */
862  band = rt_band_new_offline(
863  width, height,
864  pt,
865  hasnodata, nodataval,
866  srcnband[i] - 1, outdbfile
867  );
868  if (band == NULL) {
869  GDALClose(hdsOut);
870  if (raster != NULL)
871  rt_raster_destroy(raster);
872  if (pgraster != NULL)
873  PG_FREE_IF_COPY(pgraster, 0);
874  elog(ERROR, "RASTER_addBandOutDB: Could not create new out-db band");
875  PG_RETURN_NULL();
876  }
877 
878  if (rt_raster_add_band(raster, band, j) < 0) {
879  GDALClose(hdsOut);
880  if (raster != NULL)
881  rt_raster_destroy(raster);
882  if (pgraster != NULL)
883  PG_FREE_IF_COPY(pgraster, 0);
884  elog(ERROR, "RASTER_addBandOutDB: Could not add new out-db band to raster");
885  PG_RETURN_NULL();
886  }
887  }
888 
889  pgrtn = rt_raster_serialize(raster);
890  rt_raster_destroy(raster);
891  if (pgraster != NULL)
892  PG_FREE_IF_COPY(pgraster, 0);
893  if (!pgrtn)
894  PG_RETURN_NULL();
895 
896  SET_VARSIZE(pgrtn, pgrtn->size);
897  PG_RETURN_POINTER(pgrtn);
898 }
void * rt_raster_serialize(rt_raster raster)
Return this raster in serialized form.
Definition: rt_serialize.c:521
int rt_util_gdal_register_all(int force_register_all)
Definition: rt_util.c:334
int rt_raster_get_num_bands(rt_raster raster)
Definition: rt_raster.c:372
rt_errorstate rt_raster_same_alignment(rt_raster rast1, rt_raster rast2, int *aligned, char **reason)
raster
Be careful!! Zeros function&#39;s input parameter can be a (height x width) array, not (width x height): ...
Definition: rtrowdump.py:121
void rt_raster_set_geotransform_matrix(rt_raster raster, double *gt)
Set raster&#39;s geotransform using 6-element array.
Definition: rt_raster.c:727
void rt_raster_get_geotransform_matrix(rt_raster raster, double *gt)
Get 6-element array of raster geotransform matrix.
Definition: rt_raster.c:706
band
Definition: ovdump.py:57
gt
Definition: window.py:77
rt_pixtype
Definition: librtcore.h:185
int rt_raster_is_empty(rt_raster raster)
Return TRUE if the raster is empty.
Definition: rt_raster.c:1338
#define SRID_UNKNOWN
Unknown SRID value.
Definition: liblwgeom.h:188
rt_pixtype rt_util_gdal_datatype_to_pixtype(GDALDataType gdt)
Convert GDALDataType to rt_pixtype.
Definition: rt_util.c:153
void rt_raster_set_srid(rt_raster raster, int32_t srid)
Set raster&#39;s SRID.
Definition: rt_raster.c:363
int32_t rt_raster_get_srid(rt_raster raster)
Get raster&#39;s SRID.
Definition: rt_raster.c:356
void rt_raster_destroy(rt_raster raster)
Release memory associated to a raster.
Definition: rt_raster.c:82
rt_raster rt_raster_new(uint32_t width, uint32_t height)
Construct a raster with given dimensions.
Definition: rt_raster.c:48
uint16_t rt_raster_get_width(rt_raster raster)
Definition: rt_raster.c:121
#define FALSE
Definition: dbfopen.c:168
Struct definitions.
Definition: librtcore.h:2201
int rt_raster_add_band(rt_raster raster, rt_band band, int index)
Add band data to a raster.
Definition: rt_raster.c:405
rt_errorstate rt_util_gdal_sr_auth_info(GDALDatasetH hds, char **authname, char **authcode)
Get auth name and code.
Definition: rt_util.c:270
uint16_t rt_raster_get_height(rt_raster raster)
Definition: rt_raster.c:129
#define POSTGIS_RT_DEBUG(level, msg)
Definition: rtpostgis.h:61
#define TRUE
Definition: dbfopen.c:169
rt_raster rt_raster_deserialize(void *serialized, int header_only)
Return a raster from a serialized form.
Definition: rt_serialize.c:717
GDALDatasetH rt_util_gdal_open(const char *fn, GDALAccess fn_access, int shared)
Definition: rt_util.c:379
rt_band rt_band_new_offline(uint16_t width, uint16_t height, rt_pixtype pixtype, uint32_t hasnodata, double nodataval, uint8_t bandNum, const char *path)
Create an out-db rt_band.
Definition: rt_band.c:119
Here is the call graph for this function:
Here is the caller graph for this function: