@@ -991,18 +991,15 @@ GDALDatasetH GDALRasterize(const char *pszDest, GDALDatasetH hDstDS,
991991
992992 std::unique_ptr<GDALRasterizeOptions, decltype (&GDALRasterizeOptionsFree)>
993993 psOptionsToFree (nullptr , GDALRasterizeOptionsFree);
994- const GDALRasterizeOptions *psOptions = psOptionsIn;
995- if (psOptions == nullptr )
996- {
997- psOptionsToFree.reset (GDALRasterizeOptionsNew (nullptr , nullptr ));
998- psOptions = psOptionsToFree.get ();
999- }
994+ GDALRasterizeOptions sOptions ;
995+ if (psOptionsIn)
996+ sOptions = *psOptionsIn;
1000997
1001998 const bool bCloseOutDSOnError = hDstDS == nullptr ;
1002999 if (pszDest == nullptr )
10031000 pszDest = GDALGetDescription (hDstDS);
10041001
1005- if (psOptions-> osSQL .empty () && psOptions-> aosLayers .empty () &&
1002+ if (sOptions . osSQL .empty () && sOptions . aosLayers .empty () &&
10061003 GDALDatasetGetLayerCount (hSrcDataset) != 1 )
10071004 {
10081005 CPLError (CE_Failure, CPLE_NotSupported,
@@ -1017,13 +1014,13 @@ GDALDatasetH GDALRasterize(const char *pszDest, GDALDatasetH hDstDS,
10171014 /* Open target raster file. Eventually we will add optional */
10181015 /* creation. */
10191016 /* -------------------------------------------------------------------- */
1020- const bool bCreateOutput = psOptions-> bCreateOutput || hDstDS == nullptr ;
1017+ const bool bCreateOutput = sOptions . bCreateOutput || hDstDS == nullptr ;
10211018
10221019 GDALDriverH hDriver = nullptr ;
10231020 if (bCreateOutput)
10241021 {
10251022 CPLString osFormat;
1026- if (psOptions-> osFormat .empty ())
1023+ if (sOptions . osFormat .empty ())
10271024 {
10281025 osFormat = GetOutputDriverForRaster (pszDest);
10291026 if (osFormat.empty ())
@@ -1033,7 +1030,7 @@ GDALDatasetH GDALRasterize(const char *pszDest, GDALDatasetH hDstDS,
10331030 }
10341031 else
10351032 {
1036- osFormat = psOptions-> osFormat ;
1033+ osFormat = sOptions . osFormat ;
10371034 }
10381035
10391036 /* --------------------------------------------------------------------
@@ -1072,16 +1069,131 @@ GDALDatasetH GDALRasterize(const char *pszDest, GDALDatasetH hDstDS,
10721069 }
10731070 }
10741071
1072+ auto calculateSize = [&](const OGREnvelope &sEnvelope ) -> bool
1073+ {
1074+ const double width{sEnvelope .MaxX - sEnvelope .MinX };
1075+ if (std::isnan (width))
1076+ {
1077+ return false ;
1078+ }
1079+
1080+ const double height{sEnvelope .MaxY - sEnvelope .MinY };
1081+ if (std::isnan (height))
1082+ {
1083+ return false ;
1084+ }
1085+
1086+ if (height == 0 || width == 0 )
1087+ {
1088+ return false ;
1089+ }
1090+
1091+ if (sOptions .nXSize == 0 )
1092+ {
1093+ const double xSize{
1094+ (sEnvelope .MaxX - sEnvelope .MinX ) /
1095+ ((sEnvelope .MaxY - sEnvelope .MinY ) / sOptions .nYSize )};
1096+ if (std::isnan (xSize) || xSize > std::numeric_limits<int >::max () ||
1097+ xSize < std::numeric_limits<int >::min ())
1098+ {
1099+ return false ;
1100+ }
1101+ sOptions .nXSize = static_cast <int >(xSize);
1102+ }
1103+ else
1104+ {
1105+ const double ySize{
1106+ (sEnvelope .MaxY - sEnvelope .MinY ) /
1107+ ((sEnvelope .MaxX - sEnvelope .MinX ) / sOptions .nXSize )};
1108+ if (std::isnan (ySize) || ySize > std::numeric_limits<int >::max () ||
1109+ ySize < std::numeric_limits<int >::min ())
1110+ {
1111+ return false ;
1112+ }
1113+ sOptions .nYSize = static_cast <int >(ySize);
1114+ }
1115+ return sOptions .nXSize > 0 && sOptions .nYSize > 0 ;
1116+ };
1117+
1118+ const int nLayerCount =
1119+ (sOptions .osSQL .empty () && sOptions .aosLayers .empty ())
1120+ ? 1
1121+ : static_cast <int >(sOptions .aosLayers .size ());
1122+
1123+ const bool bOneSizeNeedsCalculation{
1124+ static_cast <bool >((sOptions .nXSize == 0 ) ^ (sOptions .nYSize == 0 ))};
1125+
1126+ // Calculate the size if either nXSize or nYSize is 0
1127+ if (sOptions .osSQL .empty () && bOneSizeNeedsCalculation)
1128+ {
1129+ CPLErr eErr = CE_None;
1130+ // Get the extent of the source dataset
1131+ OGREnvelope sEnvelope ;
1132+ bool bFirstLayer = true ;
1133+ for (int i = 0 ; i < nLayerCount; i++)
1134+ {
1135+ OGRLayerH hLayer;
1136+ if (sOptions .aosLayers .size () > static_cast <size_t >(i))
1137+ hLayer = GDALDatasetGetLayerByName (
1138+ hSrcDataset, sOptions .aosLayers [i].c_str ());
1139+ else
1140+ hLayer = GDALDatasetGetLayer (hSrcDataset, 0 );
1141+ if (hLayer == nullptr )
1142+ {
1143+ CPLError (CE_Failure, CPLE_AppDefined,
1144+ " Unable to find layer \" %s\" ." ,
1145+ sOptions .aosLayers .size () > static_cast <size_t >(i)
1146+ ? sOptions .aosLayers [i].c_str ()
1147+ : " 0" );
1148+ eErr = CE_Failure;
1149+ break ;
1150+ }
1151+ OGREnvelope sLayerEnvelop ;
1152+ if (OGR_L_GetExtent (hLayer, &sLayerEnvelop , TRUE ) != OGRERR_NONE)
1153+ {
1154+ CPLError (CE_Failure, CPLE_AppDefined,
1155+ " Cannot get layer extent" );
1156+ eErr = CE_Failure;
1157+ break ;
1158+ }
1159+ if (bFirstLayer)
1160+ {
1161+ sEnvelope = sLayerEnvelop ;
1162+ bFirstLayer = false ;
1163+ }
1164+ else
1165+ {
1166+ sEnvelope .Merge (sLayerEnvelop );
1167+ }
1168+ }
1169+
1170+ if (!calculateSize (sEnvelope ))
1171+ {
1172+ CPLError (CE_Failure, CPLE_AppDefined,
1173+ " Cannot calculate size from layer extent" );
1174+ eErr = CE_Failure;
1175+ }
1176+
1177+ if (eErr == CE_Failure)
1178+ {
1179+ if (bCloseOutDSOnError && hDstDS)
1180+ {
1181+ GDALClose (hDstDS);
1182+ }
1183+ return nullptr ;
1184+ }
1185+ }
1186+
10751187 const auto GetOutputDataType = [&](OGRLayerH hLayer)
10761188 {
10771189 CPLAssert (bCreateOutput);
10781190 CPLAssert (hDriver);
1079- GDALDataType eOutputType = psOptions-> eOutputType ;
1080- if (eOutputType == GDT_Unknown && !psOptions-> osBurnAttribute .empty ())
1191+ GDALDataType eOutputType = sOptions . eOutputType ;
1192+ if (eOutputType == GDT_Unknown && !sOptions . osBurnAttribute .empty ())
10811193 {
10821194 OGRFeatureDefnH hLayerDefn = OGR_L_GetLayerDefn (hLayer);
10831195 const int iBurnField = OGR_FD_GetFieldIndex (
1084- hLayerDefn, psOptions-> osBurnAttribute .c_str ());
1196+ hLayerDefn, sOptions . osBurnAttribute .c_str ());
10851197 if (iBurnField >= 0 && OGR_Fld_GetType (OGR_FD_GetFieldDefn (
10861198 hLayerDefn, iBurnField)) == OFTInteger64)
10871199 {
@@ -1103,36 +1215,56 @@ GDALDatasetH GDALRasterize(const char *pszDest, GDALDatasetH hDstDS,
11031215
11041216 // Store SRS handle
11051217 OGRSpatialReferenceH hSRS =
1106- psOptions-> oOutputSRS .IsEmpty ()
1218+ sOptions . oOutputSRS .IsEmpty ()
11071219 ? nullptr
11081220 : OGRSpatialReference::ToHandle (
1109- const_cast <OGRSpatialReference *>(&psOptions-> oOutputSRS ));
1221+ const_cast <OGRSpatialReference *>(&sOptions . oOutputSRS ));
11101222
11111223 /* -------------------------------------------------------------------- */
11121224 /* Process SQL request. */
11131225 /* -------------------------------------------------------------------- */
11141226 CPLErr eErr = CE_Failure;
11151227
1116- if (!psOptions-> osSQL .empty ())
1228+ if (!sOptions . osSQL .empty ())
11171229 {
11181230 OGRLayerH hLayer =
1119- GDALDatasetExecuteSQL (hSrcDataset, psOptions-> osSQL .c_str (),
1120- nullptr , psOptions-> osDialect .c_str ());
1231+ GDALDatasetExecuteSQL (hSrcDataset, sOptions . osSQL .c_str (), nullptr ,
1232+ sOptions . osDialect .c_str ());
11211233 if (hLayer != nullptr )
11221234 {
1235+
1236+ if (bOneSizeNeedsCalculation)
1237+ {
1238+ OGREnvelope sEnvelope ;
1239+ bool bSizeCalculationError{
1240+ OGR_L_GetExtent (hLayer, &sEnvelope , TRUE ) != OGRERR_NONE};
1241+ if (!bSizeCalculationError)
1242+ {
1243+ bSizeCalculationError = !calculateSize (sEnvelope );
1244+ }
1245+
1246+ if (bSizeCalculationError)
1247+ {
1248+ CPLError (CE_Failure, CPLE_AppDefined,
1249+ " Cannot get layer extent" );
1250+ GDALDatasetReleaseResultSet (hSrcDataset, hLayer);
1251+ return nullptr ;
1252+ }
1253+ }
1254+
11231255 if (bCreateOutput)
11241256 {
11251257 std::vector<OGRLayerH> ahLayers;
11261258 ahLayers.push_back (hLayer);
11271259
11281260 const GDALDataType eOutputType = GetOutputDataType (hLayer);
11291261 hDstDS = CreateOutputDataset (
1130- ahLayers, hSRS, psOptions-> sEnvelop , hDriver, pszDest,
1131- psOptions-> nXSize , psOptions-> nYSize , psOptions-> dfXRes ,
1132- psOptions-> dfYRes , psOptions-> bTargetAlignedPixels ,
1133- static_cast <int >(psOptions-> anBandList .size ()), eOutputType,
1134- psOptions-> aosCreationOptions , psOptions-> adfInitVals ,
1135- psOptions-> osNoData .c_str ());
1262+ ahLayers, hSRS, sOptions . sEnvelop , hDriver, pszDest,
1263+ sOptions . nXSize , sOptions . nYSize , sOptions . dfXRes ,
1264+ sOptions . dfYRes , sOptions . bTargetAlignedPixels ,
1265+ static_cast <int >(sOptions . anBandList .size ()), eOutputType,
1266+ sOptions . aosCreationOptions , sOptions . adfInitVals ,
1267+ sOptions . osNoData .c_str ());
11361268 if (hDstDS == nullptr )
11371269 {
11381270 GDALDatasetReleaseResultSet (hSrcDataset, hLayer);
@@ -1141,11 +1273,10 @@ GDALDatasetH GDALRasterize(const char *pszDest, GDALDatasetH hDstDS,
11411273 }
11421274
11431275 eErr = ProcessLayer (
1144- hLayer, hSRS != nullptr , hDstDS, psOptions->anBandList ,
1145- psOptions->adfBurnValues , psOptions->b3D , psOptions->bInverse ,
1146- psOptions->osBurnAttribute .c_str (),
1147- psOptions->aosRasterizeOptions , psOptions->aosTO ,
1148- psOptions->pfnProgress , psOptions->pProgressData );
1276+ hLayer, hSRS != nullptr , hDstDS, sOptions .anBandList ,
1277+ sOptions .adfBurnValues , sOptions .b3D , sOptions .bInverse ,
1278+ sOptions .osBurnAttribute .c_str (), sOptions .aosRasterizeOptions ,
1279+ sOptions .aosTO , sOptions .pfnProgress , sOptions .pProgressData );
11491280
11501281 GDALDatasetReleaseResultSet (hSrcDataset, hLayer);
11511282 }
@@ -1154,31 +1285,27 @@ GDALDatasetH GDALRasterize(const char *pszDest, GDALDatasetH hDstDS,
11541285 /* -------------------------------------------------------------------- */
11551286 /* Create output file if necessary. */
11561287 /* -------------------------------------------------------------------- */
1157- const int nLayerCount =
1158- (psOptions->osSQL .empty () && psOptions->aosLayers .empty ())
1159- ? 1
1160- : static_cast <int >(psOptions->aosLayers .size ());
11611288
11621289 if (bCreateOutput && hDstDS == nullptr )
11631290 {
11641291 std::vector<OGRLayerH> ahLayers;
11651292
1166- GDALDataType eOutputType = psOptions-> eOutputType ;
1293+ GDALDataType eOutputType = sOptions . eOutputType ;
11671294
11681295 for (int i = 0 ; i < nLayerCount; i++)
11691296 {
11701297 OGRLayerH hLayer;
1171- if (psOptions-> aosLayers .size () > static_cast <size_t >(i))
1298+ if (sOptions . aosLayers .size () > static_cast <size_t >(i))
11721299 hLayer = GDALDatasetGetLayerByName (
1173- hSrcDataset, psOptions-> aosLayers [i].c_str ());
1300+ hSrcDataset, sOptions . aosLayers [i].c_str ());
11741301 else
11751302 hLayer = GDALDatasetGetLayer (hSrcDataset, 0 );
11761303 if (hLayer == nullptr )
11771304 {
11781305 CPLError (CE_Failure, CPLE_AppDefined,
11791306 " Unable to find layer \" %s\" ." ,
1180- psOptions-> aosLayers .size () > static_cast <size_t >(i)
1181- ? psOptions-> aosLayers [i].c_str ()
1307+ sOptions . aosLayers .size () > static_cast <size_t >(i)
1308+ ? sOptions . aosLayers [i].c_str ()
11821309 : " 0" );
11831310 return nullptr ;
11841311 }
@@ -1197,12 +1324,12 @@ GDALDatasetH GDALRasterize(const char *pszDest, GDALDatasetH hDstDS,
11971324 }
11981325
11991326 hDstDS = CreateOutputDataset (
1200- ahLayers, hSRS, psOptions-> sEnvelop , hDriver, pszDest,
1201- psOptions-> nXSize , psOptions-> nYSize , psOptions-> dfXRes ,
1202- psOptions-> dfYRes , psOptions-> bTargetAlignedPixels ,
1203- static_cast <int >(psOptions-> anBandList .size ()), eOutputType,
1204- psOptions-> aosCreationOptions , psOptions-> adfInitVals ,
1205- psOptions-> osNoData .c_str ());
1327+ ahLayers, hSRS, sOptions . sEnvelop , hDriver, pszDest,
1328+ sOptions . nXSize , sOptions . nYSize , sOptions . dfXRes , sOptions . dfYRes ,
1329+ sOptions . bTargetAlignedPixels ,
1330+ static_cast <int >(sOptions . anBandList .size ()), eOutputType,
1331+ sOptions . aosCreationOptions , sOptions . adfInitVals ,
1332+ sOptions . osNoData .c_str ());
12061333 if (hDstDS == nullptr )
12071334 {
12081335 return nullptr ;
@@ -1216,25 +1343,25 @@ GDALDatasetH GDALRasterize(const char *pszDest, GDALDatasetH hDstDS,
12161343 for (int i = 0 ; i < nLayerCount; i++)
12171344 {
12181345 OGRLayerH hLayer;
1219- if (psOptions-> aosLayers .size () > static_cast <size_t >(i))
1346+ if (sOptions . aosLayers .size () > static_cast <size_t >(i))
12201347 hLayer = GDALDatasetGetLayerByName (hSrcDataset,
1221- psOptions-> aosLayers [i].c_str ());
1348+ sOptions . aosLayers [i].c_str ());
12221349 else
12231350 hLayer = GDALDatasetGetLayer (hSrcDataset, 0 );
12241351 if (hLayer == nullptr )
12251352 {
12261353 CPLError (CE_Failure, CPLE_AppDefined,
12271354 " Unable to find layer \" %s\" ." ,
1228- psOptions-> aosLayers .size () > static_cast <size_t >(i)
1229- ? psOptions-> aosLayers [i].c_str ()
1355+ sOptions . aosLayers .size () > static_cast <size_t >(i)
1356+ ? sOptions . aosLayers [i].c_str ()
12301357 : " 0" );
12311358 eErr = CE_Failure;
12321359 break ;
12331360 }
12341361
1235- if (!psOptions-> osWHERE .empty ())
1362+ if (!sOptions . osWHERE .empty ())
12361363 {
1237- if (OGR_L_SetAttributeFilter (hLayer, psOptions-> osWHERE .c_str ()) !=
1364+ if (OGR_L_SetAttributeFilter (hLayer, sOptions . osWHERE .c_str ()) !=
12381365 OGRERR_NONE)
12391366 {
12401367 eErr = CE_Failure;
@@ -1243,15 +1370,14 @@ GDALDatasetH GDALRasterize(const char *pszDest, GDALDatasetH hDstDS,
12431370 }
12441371
12451372 void *pScaledProgress = GDALCreateScaledProgress (
1246- 0.0 , 1.0 * (i + 1 ) / nLayerCount, psOptions-> pfnProgress ,
1247- psOptions-> pProgressData );
1373+ 0.0 , 1.0 * (i + 1 ) / nLayerCount, sOptions . pfnProgress ,
1374+ sOptions . pProgressData );
12481375
1249- eErr = ProcessLayer (hLayer, !psOptions->oOutputSRS .IsEmpty (), hDstDS,
1250- psOptions->anBandList , psOptions->adfBurnValues ,
1251- psOptions->b3D , psOptions->bInverse ,
1252- psOptions->osBurnAttribute .c_str (),
1253- psOptions->aosRasterizeOptions , psOptions->aosTO ,
1254- GDALScaledProgress, pScaledProgress);
1376+ eErr = ProcessLayer (
1377+ hLayer, !sOptions .oOutputSRS .IsEmpty (), hDstDS, sOptions .anBandList ,
1378+ sOptions .adfBurnValues , sOptions .b3D , sOptions .bInverse ,
1379+ sOptions .osBurnAttribute .c_str (), sOptions .aosRasterizeOptions ,
1380+ sOptions .aosTO , GDALScaledProgress, pScaledProgress);
12551381
12561382 GDALDestroyScaledProgress (pScaledProgress);
12571383 if (eErr != CE_None)
@@ -1454,10 +1580,11 @@ GDALRasterizeOptionsNew(char **papszArgv,
14541580 psOptions->nXSize = nXSize;
14551581 psOptions->nYSize = nYSize;
14561582
1457- if (psOptions->nXSize <= 0 || psOptions->nYSize <= 0 )
1583+ if (!( psOptions->nXSize > 0 || psOptions->nYSize > 0 ) )
14581584 {
14591585 CPLError (CE_Failure, CPLE_AppDefined,
1460- " Wrong value for -ts parameter." );
1586+ " Wrong value for -ts parameter: at least one of the "
1587+ " arguments must be greater than zero." );
14611588 return nullptr ;
14621589 }
14631590
0 commit comments