static ERL_NIF_TERM gdal_nif_tile_to_binary(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { gdal_tile_handle* ti; if (!enif_get_resource(env, argv[0], gdal_tile_RESOURCE, (void**)&ti)) { return enif_make_badarg(env); } ErlNifBinary tilefilenameBin; if (!enif_inspect_iolist_as_binary(env, argv[1], &tilefilenameBin) || (tilefilenameBin.size >= FILENAME_LEN)) { return make_error_msg(env, "filename error, maybe too long"); } char rasterFormatCode[16] = ""; if (enif_get_string(env, argv[2], rasterFormatCode, 16, ERL_NIF_LATIN1) <= 0) { return enif_make_badarg(env); } char tilefilename[FILENAME_LEN] = ""; memcpy(tilefilename, tilefilenameBin.data, tilefilenameBin.size); DEBUG("passed tilefilename: %s\r\n", tilefilename); GDALDriverH hOutDriver = GDALGetDriverByName(rasterFormatCode); if ( ! ti->options_resampling || (strcmp("antialias", ti->options_resampling) != 0) ) { char vsimemFileName[128] = ""; sprintf(vsimemFileName, "/vsimem/%s", tilefilename); GDALDatasetH tileBinDataset = GDALCreateCopy(hOutDriver, vsimemFileName, ti->dstile, FALSE, NULL, NULL, NULL); vsi_l_offset binDataLength; int bUnlinkAndSeize = FALSE; GByte* binData = VSIGetMemFileBuffer(vsimemFileName, &binDataLength, bUnlinkAndSeize); DEBUG("vsimem: %s, bin len: %d\r\n", vsimemFileName, binDataLength); ERL_NIF_TERM binTerm; unsigned char* buf = enif_make_new_binary(env, binDataLength, &binTerm); memcpy(buf, binData, binDataLength); // CPLFree(binData); GDALClose(tileBinDataset); return enif_make_tuple2(env, ATOM_OK, binTerm); } return make_error_msg(env, "wrong resampling"); }
std::size_t SyntaxicXML::check_line(std::string& balise_start, InputIterator file, OutputIterator end) const { std::string close_balise{ balise_start }; std::size_t i(0); close_balise.insert(close_balise.begin() + 1, '/'); for (file = file + 1; file != end; ++file) { std::string line{ (*file) }; std::string open; std::string close; line.erase(std::remove_if(line.begin(), line.end(), [](char c) { return c == ' ' || c == '\t'; }), line.end()); if (line == close_balise) return i; if (!check_open_balise(line, open)) throw std::runtime_error{ make_error_msg("Error, ", line, " is incorrect") }; if (!check_close_balise(line, close)) throw std::runtime_error{ make_error_msg("Error, ", line, " is incorrect") }; open.insert(open.begin() + 1, '/'); if (open != close) throw std::runtime_error{ make_error_msg("Error, ", line, " is incorrect") }; ++i; } throw std::runtime_error{ "Error, enclosing balise is missing" }; }
static ERL_NIF_TERM gdal_nif_is_imgfile(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { ErlNifBinary filenameBin; if (!enif_inspect_iolist_as_binary(env, argv[0], &filenameBin) || (filenameBin.size >= FILENAME_LEN)) { return make_error_msg(env, "filename error, maybe too long"); } char imgfilename[FILENAME_LEN] = ""; memcpy(imgfilename, filenameBin.data, filenameBin.size); DEBUG("img filename: %s\r\n", imgfilename); GDALDatasetH hDataset = GDALOpen( imgfilename, GA_ReadOnly ); if (hDataset == NULL) { return ATOM_FALSE; } else { GDALClose( hDataset ); return ATOM_TRUE; } }
static ERL_NIF_TERM gdal_nif_copyout_rawtile(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { GDALDatasetH img_ds = NULL; gdal_img_handle* hImg = NULL; if (enif_get_resource(env, argv[0], gdal_img_RESOURCE, (void**)&hImg)) { img_ds = hImg->out_ds; } else { return enif_make_badarg(env); } bandregion r, w; if (!get_bandregion_from(env, argv + 1, &r) || !get_bandregion_from(env, argv + 2, &w)) { return enif_make_badarg(env); } gdal_rawtile_handle* hRawtile = enif_alloc_resource(gdal_rawtile_RESOURCE, sizeof(*hRawtile)); *hRawtile = (gdal_rawtile_handle) { .data = NULL, .alpha = NULL, .w = w, .querysize = hImg->querysize, .tilesize = hImg->tilesize, .dataBandsCount = hImg->dataBandsCount, .tilebands = hImg->tilebands, .options_resampling = hImg->options_resampling }; ERL_NIF_TERM res = enif_make_resource(env, hRawtile); enif_release_resource(hRawtile); // hRawtile resource now only owned by "Erlang" // data buffer size when read from img AND write to tile int bufsize = w.xsize * w.ysize; DEBUG("r.xoff: %d, r.yoff: %d, r.xsz: %d, r.ysz: %d\r\n", r.xoffset, r.yoffset, r.xsize, r.ysize); DEBUG("w.xoff: %d, w.yoff: %d, w.xsz: %d, w.ysz: %d\r\n", w.xoffset, w.yoffset, w.xsize, w.ysize); DEBUG("bandscount: %d, CPLCalloc size=%zu\r\n", hImg->dataBandsCount, bufsize * hImg->dataBandsCount); hRawtile->data = (GByte*)CPLMalloc(bufsize * hImg->dataBandsCount * sizeof(*hRawtile->data)); int panBandMap[hImg->dataBandsCount]; fill_pband_list(hImg->dataBandsCount, panBandMap); CPLErr eErr = GDALDatasetRasterIO(img_ds, GF_Read, r.xoffset, r.yoffset, r.xsize, r.ysize, hRawtile->data, w.xsize, w.ysize, GDT_Byte, hImg->dataBandsCount, panBandMap, 0, 0, 0); if (eErr == CE_Failure) { char buf[128] = "DatasetRasterIO read failed: "; const char* errmsg = CPLGetLastErrorMsg(); strncat(buf, errmsg, strlen(errmsg)); return make_error_msg(env, errmsg); } // read dataset alpha hRawtile->alpha = (GByte*)CPLMalloc(bufsize * sizeof(*hRawtile->alpha)); eErr = GDALRasterIO(hImg->alphaBand, GF_Read, r.xoffset, r.yoffset, r.xsize, r.ysize, hRawtile->alpha, w.xsize, w.ysize, GDT_Byte, 0, 0); if (eErr == CE_Failure) { char buf[128] = "DatasetRasterIO read failed: "; const char* errmsg = CPLGetLastErrorMsg(); strncat(buf, errmsg, strlen(errmsg)); return make_error_msg(env, errmsg); } return enif_make_tuple2(env, ATOM_OK, res); } static ERL_NIF_TERM gdal_nif_build_tile(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { gdal_rawtile_handle* hRawtile; if (!enif_get_resource(env, argv[0], gdal_rawtile_RESOURCE, (void**)&hRawtile)) { return enif_make_badarg(env); } bandregion w = hRawtile->w; int xoffset = w.xoffset; int yoffset = w.yoffset; int xsize = w.xsize; int ysize = w.ysize; int dataBandsCount = hRawtile->dataBandsCount; int tilebands = hRawtile->tilebands; int tilesize = hRawtile->tilesize; const char *options_resampling = hRawtile->options_resampling; GDALDriverH hMemDriver = GDALGetDriverByName("MEM"); GDALDatasetH dstile = GDALCreate(hMemDriver, "", tilesize, tilesize, tilebands, GDT_Byte, NULL); GByte* data = hRawtile->data; GByte* alpha = hRawtile->alpha; CPLErr eErr = CE_None; if (hRawtile->tilesize == hRawtile->querysize) { eErr = write_data_and_alpha_to_raster(dstile, xoffset, yoffset, xsize, ysize, data, alpha, dataBandsCount, tilebands); if (eErr == CE_Failure) { return make_error_msg(env, "write_data_and_alpha_to_raster"); } // Note: For source drivers based on WaveLet compression (JPEG2000, ECW, MrSID) // the ReadRaster function returns high-quality raster (not ugly nearest neighbour) // TODO: Use directly 'near' for WaveLet files } else { GDALDriverH hMemDriver = GDALGetDriverByName("MEM"); GDALDatasetH dsquery = GDALCreate(hMemDriver, "", hRawtile->querysize, hRawtile->querysize, hRawtile->tilebands, GDT_Byte, NULL); if (dsquery == NULL) { return make_error_msg(env, "create dsquery"); } eErr = write_data_and_alpha_to_raster(dsquery, xoffset, yoffset, xsize, ysize, data, alpha, dataBandsCount, tilebands); if (eErr == CE_Failure) { GDALClose(dsquery); return make_error_msg(env, "write data and alpha to raster"); } CPLErrorReset(); eErr = scale_query_to_tile(dsquery, dstile, hRawtile->options_resampling); GDALClose(dsquery); if (eErr == CE_Failure) { return make_error_msg(env, "ScaleQueryTo_tile"); } } // free_temp_rawdata(hRawtile); gdal_tile_handle* hTile = enif_alloc_resource(gdal_tile_RESOURCE, sizeof(*hTile)); *hTile = (gdal_tile_handle) { .dstile = dstile, .options_resampling = options_resampling }; ERL_NIF_TERM builtTileRes = enif_make_resource(env, hTile); enif_release_resource(hTile); // hRawtile resource now only owned by "Erlang" return enif_make_tuple2(env, ATOM_OK, builtTileRes); }
// build out_ds static ERL_NIF_TERM gdal_nif_create_warped_vrtimg(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { ErlNifBinary filenameBin; if (!enif_inspect_iolist_as_binary(env, argv[0], &filenameBin) || (filenameBin.size >= FILENAME_LEN)) { return make_error_msg(env, "filename error, maybe too long"); } char imgfilename[FILENAME_LEN] = ""; size_t name_sz = filenameBin.size; memcpy(imgfilename, filenameBin.data, filenameBin.size); DEBUG("img filename: %s\r\n", imgfilename); int epsg_code; if (!enif_get_int(env, argv[1], &epsg_code)) { return enif_make_badarg(env); } GDALDatasetH in_ds = GDALOpenShared(imgfilename, GA_ReadOnly); if (in_ds == NULL) { const char* msg = "It is not possible to open the input file '%s'."; char errstr[name_sz + strlen(msg) + 1]; sprintf(errstr, msg, imgfilename); return make_error_msg(env, errstr); } gdal_img_handle* handle = enif_alloc_resource( gdal_img_RESOURCE, sizeof(gdal_img_handle)); memset(handle, '\0', sizeof(*handle)); handle->in_ds = in_ds; handle->options_resampling = "average"; handle->querysize = 256 * 4; handle->tilesize = 256; int rasterCount = GDALGetRasterCount(in_ds); if (rasterCount == 0) { const char* msg = "Input file '%s' has no raster band"; char errstr[name_sz + strlen(msg) + 1]; sprintf(errstr, msg, imgfilename); destroy_img_handle(handle); return make_error_msg(env, errstr); } GDALRasterBandH hBand = GDALGetRasterBand(in_ds, 1); if (GDALGetRasterColorTable(hBand) != NULL) { const char* msg = "Please convert this file to RGB/RGBA and run gdal2tiles on the result.\n" "From paletted file you can create RGBA file (temp.vrt) by:\n" "gdal_translate -of vrt -expand rgba %s temp.vrt\n" "then run this program: gdal2tiles temp.vrt"; char errstr[name_sz + strlen(msg) + 1]; sprintf(errstr, msg, imgfilename); destroy_img_handle(handle); return make_error_msg(env, errstr); } double padfTransform[6]; double errTransform[6] = {0.0, 1.0, 0.0, 0.0, 0.0, 1.0}; GDALGetGeoTransform(in_ds, padfTransform); if (0 == memcmp(padfTransform, errTransform, sizeof(errTransform)) && GDALGetGCPCount(in_ds) == 0) { destroy_img_handle(handle); return make_error_msg(env, "There is no georeference - " "neither affine transformation (worldfile) nor GCPs"); } const char* in_srs_wkt = GDALGetProjectionRef(in_ds); if (in_srs_wkt == NULL && GDALGetGCPCount(in_ds) != 0) { in_srs_wkt = GDALGetGCPProjection(in_ds); } char* out_srs_wkt = get_wkt_of(epsg_code); GDALDatasetH out_ds = GDALAutoCreateWarpedVRT(in_ds, in_srs_wkt, out_srs_wkt, GRA_NearestNeighbour, 0.0, NULL); handle->out_ds = out_ds; OGRFree(out_srs_wkt); handle->alphaBand = GDALGetMaskBand(GDALGetRasterBand(handle->out_ds, 1)); rasterCount = GDALGetRasterCount(handle->out_ds); unsigned int dataBandsCount; if (GDALGetMaskFlags(handle->alphaBand) & GMF_ALPHA || rasterCount == 4 || rasterCount == 2) { dataBandsCount = rasterCount - 1; } else { dataBandsCount = rasterCount; } handle->dataBandsCount = dataBandsCount; handle->tilebands = dataBandsCount + 1; ERL_NIF_TERM imginfo = get_imginfo(env, out_ds); if (enif_compare(ATOM_ERROR, imginfo) == 0) { destroy_img_handle(handle); return make_error_msg(env, "Georeference of the raster contains rotation or skew. " "Such raster is not supported. " "Please use gdalwarp first"); } ERL_NIF_TERM imgref = enif_make_resource(env, handle); enif_release_resource(handle); return enif_make_tuple3(env, ATOM_OK, imgref, imginfo); }