Merge remote-tracking branch 'upstream/master'

pull/52/head
Andrei Medar 2020-09-24 18:18:39 +00:00
commit cab74bc7fb
5 changed files with 372 additions and 0 deletions

3
.gitmodules vendored
View File

@ -10,3 +10,6 @@
[submodule "oss-internship-2020/curl/curl_wrapper/curl"]
path = oss-internship-2020/curl/curl_wrapper/curl
url = https://github.com/curl/curl
[submodule "oss-internship-2020/gdal/gdal"]
path = oss-internship-2020/gdal/gdal
url = https://github.com/OSGeo/gdal/tree/master/gdal

Binary file not shown.

View File

@ -0,0 +1,86 @@
# Copyright 2020 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
cmake_minimum_required(VERSION 3.10)
project(test CXX C)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED True)
find_package(PNG REQUIRED)
find_package(PkgConfig REQUIRED)
pkg_check_modules(libpcre REQUIRED IMPORTED_TARGET libpcre)
pkg_check_modules(proj REQUIRED IMPORTED_TARGET proj)
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")
target_link_libraries(libgdal INTERFACE
crypto
expat
jpeg
PkgConfig::libpcre
PkgConfig::proj
sqlite3
tiff
z
pthread
m
rt
dl
curl
PNG::PNG
)
add_sapi_library(gdal_sapi
FUNCTIONS GDALOpen
GDALAllRegister
GDALGetDatasetDriver
GDALGetDriverShortName
GDALGetDriverLongName
GDALGetGeoTransform
GDALGetRasterBand
GDALGetBlockSize
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
)

View File

@ -0,0 +1,88 @@
# GDAL Raster GeoTIFF Workflow
```
Build Tools: CMake/Ninja
OS: Linux
```
### For installing GDAL:
```
sudo apt-get install python3.6-dev
sudo add-apt-repository ppa:ubuntugis/ppa && sudo apt update
sudo apt-get install gdal-bin
sudo apt-get install libgdal-dev
```
### Dependencies:
PNG: `sudo apt-get install libpng-dev`
PCRE: `sudo apt-get install libpcre3 libpcre3-dev`
PROJ: `sudo apt-get install libproj-dev`
OBS! You may need to set `export LD_LIBRARY_PATH=/lib:/usr/lib:/usr/local/lib`.
It is required for libproj.so to be found into /usr/local/lib/. You can also fix
this by typing `locate libproj.so` which will give you
<the_absolute_libproj.so_path> and then `cp <the_absolute_libproj.so_path>
/usr/local/lib/`.
### Initializing GDAL submodule:
`git submodule add https://github.com/OSGeo/gdal/tree/master/gdal`
### Building GDAL statically
GNUmakefile from gdal/gdal can handle building the static library.
`cd gdal/gdal && make static-lib`
`cd ../.. && mkdir lib`
`cp gdal/gdal/libgdal.a lib/`
OBS! The file is huge! It may take a while.
### For testing:
`mkdir build && cd build`
`cmake .. -G Ninja`
`ninja`
`./raster <your_absolute_tiff_file_path>`
## 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
librarys 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...*
Useful functions from the `gdal.h` header are added to the SAPI library built
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.

View File

@ -0,0 +1,195 @@
// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <gflags/gflags.h>
#include <syscall.h>
#include <fstream>
#include <iostream>
#include <glog/logging.h>
#include "gdal_sapi.sapi.h" // NOLINT(build/include)
#include "sandboxed_api/sandbox2/util/fileops.h"
class GdalSapiSandbox : public GDALSandbox {
public:
GdalSapiSandbox(std::string path)
: GDALSandbox(), file_path_(std::move(path)) {}
std::unique_ptr<sandbox2::Policy> 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(file_path_)
.BuildOrDie();
}
private:
std::string file_path_;
};
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<double> adf_geo_transform(6);
sapi::v::Array<double> adf_geo_transform_array(&adf_geo_transform[0],
adf_geo_transform.size());
// For this function that returns CPLErr, the error-handling must be done
// analyzing the returning object.
// Same for GDALReturnsIO from below.
CPLErr err;
SAPI_ASSIGN_OR_RETURN(err, api.GDALGetGeoTransform(
&ptr_dataset, adf_geo_transform_array.PtrBoth()));
// If GDALGetGeoTransform generates an error.
if (err != CE_None) {
return absl::InternalError("GDAL rasterization failed.");
}
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<int> n_blockX_size(1);
std::vector<int> n_blockY_size(1);
sapi::v::Array<int> nBlockXSizeArray(&n_blockX_size[0], n_blockX_size.size());
sapi::v::Array<int> 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<int> b_got_min(1);
std::vector<int> b_got_max(1);
sapi::v::Array<int> b_got_min_array(&b_got_min[0], b_got_min.size());
sapi::v::Array<int> 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<int8_t> raster_data(nX_size.value() * nY_size.value(), -1);
sapi::v::Array<int8_t> raster_data_array(&raster_data[0], raster_data.size());
// We will use CPLErr type of returning value, as before with
// GDALGetGeoTransorm.
SAPI_ASSIGN_OR_RETURN(
err, 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));
// If GDALRasterIO generates an error.
if (err != CE_None) {
return absl::InternalError("GDAL rasterization failed.");
}
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;
}