diff --git a/oss-internship-2020/gdal/CANYrelief1-geo.tif b/oss-internship-2020/gdal/CANYrelief1-geo.tif new file mode 100644 index 0000000..f9d2ef0 Binary files /dev/null and b/oss-internship-2020/gdal/CANYrelief1-geo.tif differ diff --git a/oss-internship-2020/gdal/CMakeLists.txt b/oss-internship-2020/gdal/CMakeLists.txt new file mode 100644 index 0000000..04db225 --- /dev/null +++ b/oss-internship-2020/gdal/CMakeLists.txt @@ -0,0 +1,56 @@ +cmake_minimum_required(VERSION 3.10) + +project(test CXX C) + +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED True) + +set(SAPI_ROOT "${PROJECT_SOURCE_DIR}/../.." CACHE PATH "Path to the Sandboxed API source tree") +# cmake .. -G Ninja -DSAPI_ROOT=$HOME/sapi_root + +set(SAPI_ENABLE_EXAMPLES OFF CACHE BOOL "") +set(SAPI_ENABLE_TESTS OFF CACHE BOOL "") +add_subdirectory("${SAPI_ROOT}" + "${CMAKE_BINARY_DIR}/sandboxed-api-build" + # Omit this to have the full Sandboxed API in IDE + EXCLUDE_FROM_ALL) + +add_library(libgdal STATIC IMPORTED) +set_property(TARGET libgdal PROPERTY IMPORTED_LOCATION "${CMAKE_CURRENT_SOURCE_DIR}/lib/libgdal.a") + +find_package(PNG REQUIRED) + +target_link_libraries(libgdal INTERFACE + crypto expat jpeg + /usr/lib/x86_64-linux-gnu/libproj.so + /usr/lib/x86_64-linux-gnu/libpcre.so + sqlite3 tiff z pthread m rt dl curl + PNG::PNG) + +add_sapi_library(gdal_sapi + FUNCTIONS GDALOpen GDALAllRegister GDALGetDatasetDriver + GDALGetDriverShortName GDALGetDriverLongName GDALGetRasterXSize + GDALGetRasterYSize GDALGetRasterCount GDALGetProjectionRef + GDALOpenEx GDALGetGeoTransform GDALGetRasterBand GDALGetBlockSize + GDALGetRasterMinimum GDALGetRasterMaximum GDALGetRasterBandXSize + GDALGetRasterBandYSize GDALRasterIO + + INPUTS "/usr/include/gdal/gdal.h" + LIBRARY libgdal + LIBRARY_NAME gdal + + NAMESPACE "" +) + +target_include_directories(gdal_sapi INTERFACE + "${PROJECT_BINARY_DIR}" +) + +add_executable(raster + raster.cc +) + +target_link_libraries(raster + gdal_sapi + sapi::sapi +) diff --git a/oss-internship-2020/gdal/README.md b/oss-internship-2020/gdal/README.md new file mode 100644 index 0000000..c4e1999 --- /dev/null +++ b/oss-internship-2020/gdal/README.md @@ -0,0 +1,53 @@ +# GDAL Raster GeoTIFF Workflow + +``` +Build Tools: CMake/Ninja +OS: Linux +``` + +### For testing: +`mkdir build && cd build` + +`cmake .. -G Ninja` + +`ninja` + +`./raster` + +## About the project + GDAL is a translator library for raster and vector + geospatial data format. + The project consist in rastering a GeoTIFF file format + using GDAL functionalities and sandboxed methods. + +## Implementation + +*Sandboxing...* + + The purpose of sandboxing is to limit the permissions + and capabilities of library’s methods, in order to + secure the usage of them. After obtaining the sandbox, + the functions will be called through an Sandbox API + (being called api in the current test) and so, the + operations, system calls or namspaces access may be + controlled. + +*Raster process...* + + From gdal.h header useful methods are added to sapi + library builded with CMake. + + One .tiff file is manipulated with GDALOpen + functionality, which extracts a pointer to the data set + containg a list of raster bands, all pertaining to the + same area. + Metadata, a coordinate system, a georeferencing + transform, size of raster and various other information + are kept into the data set that corresponds to the image. + + To create an array containing the image information, the + dimentions needed are extracted using some specific + GDAL(X/Y)Size functions applied to the block. + GDALRasterBand function takes care of data type conversion, one more step following: placing the + converted data (with RasterIO method) into the created + and well allocated structure. diff --git a/oss-internship-2020/gdal/raster.cc b/oss-internship-2020/gdal/raster.cc new file mode 100644 index 0000000..7b971d1 --- /dev/null +++ b/oss-internship-2020/gdal/raster.cc @@ -0,0 +1,163 @@ +#include +#include +#include + +#include +#include + +#include "gdal_sapi.sapi.h" +#include "sandboxed_api/sandbox2/util/fileops.h" + +class GdalSapiSandbox : public gdalSandbox { + public: + std::string filePath; + + GdalSapiSandbox(std::string path) + : gdalSandbox(), filePath(std::move(path)) {} + + std::unique_ptr ModifyPolicy( + sandbox2::PolicyBuilder*) override { + return sandbox2::PolicyBuilder() + .AllowDynamicStartup() + .AllowRead() + .AllowSystemMalloc() + .AllowWrite() + .AllowExit() + .AllowStat() + .AllowOpen() + .AllowSyscalls({ + __NR_futex, + __NR_close, + __NR_recvmsg, + __NR_getdents64, + __NR_lseek, + __NR_getpid, + __NR_sysinfo, + __NR_prlimit64, + __NR_ftruncate, + __NR_unlink, + }) + .AddFile(filePath) + .BuildOrDie(); + } +}; + +absl::Status GdalMain(std::string filename) { + // Reading GDALDataset from a (local, specific) file. + GdalSapiSandbox sandbox(filename); + SAPI_RETURN_IF_ERROR(sandbox.Init()); + gdalApi api(&sandbox); + + sapi::v::CStr s(filename.data()); + + SAPI_RETURN_IF_ERROR(api.GDALAllRegister()); + auto open = api.GDALOpen(s.PtrBoth(), GDALAccess::GA_ReadOnly); + + LOG(INFO) << "Dataset pointer adress: " << open.value() << std::endl; + sapi::v::RemotePtr ptr_dataset(open.value()); + + LOG(INFO) << ptr_dataset.ToString() << std::endl; + if (!open.value()) { + return absl::AbortedError("NULL pointer for Dataset.\n"); + } + + // Printing some general information about the dataset. + auto driver = api.GDALGetDatasetDriver(&ptr_dataset); + sapi::v::RemotePtr ptr_driver(driver.value()); + + auto driver_short_name = api.GDALGetDriverShortName(&ptr_driver); + auto driver_long_name = api.GDALGetDriverLongName(&ptr_driver); + + sapi::v::RemotePtr ptr_driver_short_name(driver_short_name.value()); + sapi::v::RemotePtr ptr_driver_long_name(driver_long_name.value()); + + LOG(INFO) << "Driver short name: " + << sandbox.GetCString(ptr_driver_short_name).value().c_str(); + LOG(INFO) << "Driver long name: " + << sandbox.GetCString(ptr_driver_long_name).value().c_str(); + + // Checking that GetGeoTransform is valid. + std::vector adf_geo_transform(6); + sapi::v::Array adfGeoTransformArray(&adf_geo_transform[0], + adf_geo_transform.size()); + + api.GDALGetGeoTransform(&ptr_dataset, adfGeoTransformArray.PtrBoth()) + .IgnoreError(); + + LOG(INFO) << "Origin = (" << adf_geo_transform[0] << ", " + << adf_geo_transform[3] << ")" << std::endl; + LOG(INFO) << "Pixel Size = (" << adf_geo_transform[0] << ", " + << adf_geo_transform[3] << ")" << std::endl; + + std::vector n_blockX_size(1); + std::vector n_blockY_size(1); + + sapi::v::Array nBlockXSizeArray(&n_blockX_size[0], n_blockX_size.size()); + sapi::v::Array nBlockYSizeArray(&n_blockY_size[0], n_blockY_size.size()); + + auto band = api.GDALGetRasterBand(&ptr_dataset, 1); + LOG(INFO) << "Band pointer adress: " << band.value() << std::endl; + if (!band.value()) { + return absl::AbortedError("NULL pointer for Band.\n"); + } + + sapi::v::RemotePtr ptr_band(band.value()); + SAPI_RETURN_IF_ERROR(api.GDALGetBlockSize( + &ptr_band, nBlockXSizeArray.PtrBoth(), nBlockYSizeArray.PtrBoth())); + + LOG(INFO) << "Block = " << n_blockX_size[0] << " x " << n_blockY_size[0] + << std::endl; + + std::vector b_got_min(1); + std::vector b_got_max(1); + + sapi::v::Array b_got_min_array(&b_got_min[0], b_got_min.size()); + sapi::v::Array b_got_max_array(&b_got_max[0], b_got_max.size()); + + auto nX_size = api.GDALGetRasterBandXSize(&ptr_band); + auto nY_size = api.GDALGetRasterBandYSize(&ptr_band); + + std::vector raster_data(nX_size.value() * nY_size.value(), -1); + sapi::v::Array raster_data_array(&raster_data[0], raster_data.size()); + + api.GDALRasterIO(&ptr_band, GF_Read, 0, 0, nX_size.value(), nY_size.value(), + raster_data_array.PtrBoth(), nX_size.value(), + nY_size.value(), GDT_Byte, 0, 0) + .IgnoreError(); + + std::cout << "Raster data info: " << raster_data_array.ToString() + << std::endl; + + // To print the data content: `std::cout << raster_data_array.GetData() << + // std::endl;` + + return absl::OkStatus(); +} + +int main(int argc, char** argv) { + // The file to be converted should be specified in the first argument while + // running the program. + if (argc < 2) { + std::cout << "You need to provide a file name: ./raster " + "your_tiff_file_absolute_path\n" + "Example: ./raster /usr/home/username/file.tiff" + << std::endl; + return EXIT_FAILURE; + } + + std::ifstream aux_file; + aux_file.open(argv[1]); + if (!aux_file.is_open()) { + std::cout << "Your file name is not valid.\nUnable to open the file." + << std::endl; + return EXIT_FAILURE; + } + std::string filename(argv[1]); + + if (absl::Status status = GdalMain(filename); !status.ok()) { + LOG(ERROR) << "Initialization failed: " << status.ToString(); + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +}