Return a raster from a GDAL dataset.
2175 {
2178 CPLErr cplerr;
2179 uint32_t width = 0;
2180 uint32_t height = 0;
2181 uint32_t numBands = 0;
2182 uint32_t i = 0;
2183 char *authname = NULL;
2184 char *authcode = NULL;
2185
2186 GDALRasterBandH gdband = NULL;
2187 GDALDataType gdpixtype = GDT_Unknown;
2189 int32_t idx;
2191 uint32_t ptlen = 0;
2192 int hasnodata = 0;
2193 double nodataval;
2194
2197
2198 uint32_t nXBlocks, nYBlocks;
2199 int nXBlockSize, nYBlockSize;
2200 uint32_t iXBlock, iYBlock;
2201 uint32_t nXValid, nYValid;
2202 uint32_t iY;
2203
2204 uint8_t *values = NULL;
2205 uint32_t valueslen = 0;
2206 uint8_t *ptr = NULL;
2207
2208 assert(NULL != ds);
2209
2210
2211 width = GDALGetRasterXSize(ds);
2212 height = GDALGetRasterYSize(ds);
2213 RASTER_DEBUGF(3,
"Raster dimensions (width x height): %d x %d", width, height);
2214
2215
2218 if (NULL == rast) {
2219 rterror(
"rt_raster_from_gdal_dataset: Out of memory allocating new raster");
2220 return NULL;
2221 }
2223
2224
2225 cplerr = GDALGetGeoTransform(ds, gt);
2226 if (GDALGetGeoTransform(ds, gt) != CE_None) {
2227 RASTER_DEBUG(4,
"Using default geotransform matrix (0, 1, 0, 0, 0, -1)");
2234 }
2235
2236
2238
2239 RASTER_DEBUGF(3,
"Raster geotransform (%f, %f, %f, %f, %f, %f)",
2240 gt[0], gt[1], gt[2], gt[3], gt[4], gt[5]);
2241
2242
2244 if (
2245 authname != NULL &&
2246 strcmp(authname, "EPSG") == 0 &&
2247 authcode != NULL
2248 ) {
2251 }
2252
2253 if (authname != NULL)
2255 if (authcode != NULL)
2257 }
2258
2259 numBands = GDALGetRasterCount(ds);
2260
2261#if POSTGIS_DEBUG_LEVEL > 3
2262 for (i = 1; i <= numBands; i++) {
2263 GDALRasterBandH _grb = NULL;
2264 double _min;
2265 double _max;
2266 double _mean;
2267 double _stddev;
2268
2269 _grb = GDALGetRasterBand(ds, i);
2270 GDALComputeRasterStatistics(_grb,
FALSE, &_min, &_max, &_mean, &_stddev, NULL, NULL);
2271 RASTER_DEBUGF(4,
"GDAL Band %d stats: %f, %f, %f, %f", i, _min, _max, _mean, _stddev);
2272 }
2273#endif
2274
2275
2276 for (i = 1; i <= numBands; i++) {
2278 gdband = NULL;
2279 gdband = GDALGetRasterBand(ds, i);
2280 if (NULL == gdband) {
2281 rterror(
"rt_raster_from_gdal_dataset: Could not get GDAL band");
2283 return NULL;
2284 }
2286
2287
2288 gdpixtype = GDALGetRasterDataType(gdband);
2289 RASTER_DEBUGF(4,
"gdpixtype, size = %s, %d", GDALGetDataTypeName(gdpixtype), GDALGetDataTypeSizeBytes(gdpixtype));
2292 rterror(
"rt_raster_from_gdal_dataset: Unknown pixel type for GDAL band");
2294 return NULL;
2295 }
2297
2298
2299 width = GDALGetRasterBandXSize(gdband);
2300 height = GDALGetRasterBandYSize(gdband);
2301 RASTER_DEBUGF(3,
"GDAL band dimensions (width x height): %d x %d", width, height);
2302
2303
2304 nodataval = GDALGetRasterNoDataValue(gdband, &hasnodata);
2305 RASTER_DEBUGF(3,
"(hasnodata, nodataval) = (%d, %f)", hasnodata, nodataval);
2306
2307
2309 rast, pt,
2310 (hasnodata ? nodataval : 0),
2312 );
2313 if (idx < 0) {
2314 rterror(
"rt_raster_from_gdal_dataset: Could not allocate memory for raster band");
2316 return NULL;
2317 }
2320
2321
2322 GDALGetBlockSize(gdband, &nXBlockSize, &nYBlockSize);
2323 nXBlocks = (width + nXBlockSize - 1) / nXBlockSize;
2324 nYBlocks = (height + nYBlockSize - 1) / nYBlockSize;
2325 RASTER_DEBUGF(4,
"(nXBlockSize, nYBlockSize) = (%d, %d)", nXBlockSize, nYBlockSize);
2326 RASTER_DEBUGF(4,
"(nXBlocks, nYBlocks) = (%d, %d)", nXBlocks, nYBlocks);
2327
2328
2329 valueslen = ptlen * nXBlockSize * nYBlockSize;
2331 if (values == NULL) {
2332 rterror(
"rt_raster_from_gdal_dataset: Could not allocate memory for GDAL band pixel values");
2334 return NULL;
2335 }
2336 RASTER_DEBUGF(3,
"values @ %p of length = %d", values, valueslen);
2337
2338 for (iYBlock = 0; iYBlock < nYBlocks; iYBlock++) {
2339 for (iXBlock = 0; iXBlock < nXBlocks; iXBlock++) {
2340 x = iXBlock * nXBlockSize;
2341 y = iYBlock * nYBlockSize;
2342 RASTER_DEBUGF(4,
"(iXBlock, iYBlock) = (%d, %d)", iXBlock, iYBlock);
2344
2345 memset(values, 0, valueslen);
2346
2347
2348 if ((iXBlock + 1) * nXBlockSize > width)
2349 nXValid = width - (iXBlock * nXBlockSize);
2350 else
2351 nXValid = nXBlockSize;
2352
2353
2354 if ((iYBlock + 1) * nYBlockSize > height)
2355 nYValid = height - (iYBlock * nYBlockSize);
2356 else
2357 nYValid = nYBlockSize;
2358
2359 RASTER_DEBUGF(4,
"(nXValid, nYValid) = (%d, %d)", nXValid, nYValid);
2360
2361 cplerr = GDALRasterIO(
2362 gdband, GF_Read,
2363 x, y,
2364 nXValid, nYValid,
2365 values, nXValid, nYValid,
2366 gdpixtype,
2367 0, 0
2368 );
2369 if (cplerr != CE_None) {
2370 rterror(
"rt_raster_from_gdal_dataset: Could not get data from GDAL raster");
2373 return NULL;
2374 }
2375
2376
2377 if (nXBlocks == 1 && nYBlockSize > 1 && nXValid == width) {
2379 y = nYBlockSize * iYBlock;
2380
2381 RASTER_DEBUGF(4,
"Setting set of pixel lines at (%d, %d) for %d pixels", x, y, nXValid * nYValid);
2383 }
2384 else {
2385 ptr = values;
2386 x = nXBlockSize * iXBlock;
2387 for (iY = 0; iY < nYValid; iY++) {
2388 y = iY + (nYBlockSize * iYBlock);
2389
2390 RASTER_DEBUGF(4,
"Setting pixel line at (%d, %d) for %d pixels", x, y, nXValid);
2392 ptr += (nXValid * ptlen);
2393 }
2394 }
2395 }
2396 }
2397
2398
2400 }
2401
2403}
void rterror(const char *fmt,...) __attribute__((format(printf
Wrappers used for reporting errors and info.
void * rtalloc(size_t size)
Wrappers used for managing memory.
rt_pixtype rt_util_gdal_datatype_to_pixtype(GDALDataType gdt)
Convert GDALDataType to rt_pixtype.
#define RASTER_DEBUG(level, msg)
#define RASTER_DEBUGF(level, msg,...)
rt_errorstate rt_band_set_pixel_line(rt_band band, int x, int y, void *vals, uint32_t len)
Set values of multiple pixels.
void rtdealloc(void *mem)
rt_errorstate rt_util_gdal_sr_auth_info(GDALDatasetH hds, char **authname, char **authcode)
Get auth name and code.
int rt_pixtype_size(rt_pixtype pixtype)
Return size in bytes of a value in the given pixtype.
int rt_raster_generate_new_band(rt_raster raster, rt_pixtype pixtype, double initialvalue, uint32_t hasnodata, double nodatavalue, int index)
Generate a new inline band and add it to a raster.
void rt_raster_set_geotransform_matrix(rt_raster raster, double *gt)
Set raster's geotransform using 6-element array.
void rt_raster_destroy(rt_raster raster)
Release memory associated to a raster.
rt_raster rt_raster_new(uint32_t width, uint32_t height)
Construct a raster with given dimensions.
uint16_t rt_raster_get_num_bands(rt_raster raster)
rt_band rt_raster_get_band(rt_raster raster, int n)
Return Nth band, or NULL if unavailable.
void rt_raster_set_srid(rt_raster raster, int32_t srid)
Set raster's SRID.