1 // Copyright 2020 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "gtiff_converter.h" // NOLINT(build/include)
16
17 #include "sandboxed_api/util/fileops.h"
18
19 namespace gdal::sandbox {
20
21 namespace {
22
23 inline constexpr absl::string_view kDriverName = "GTiff";
24
25 } // namespace
26
RasterToGTiffProcessor(std::string out_file_full_path,std::string proj_db_path,parser::RasterDataset data,int retry_count)27 RasterToGTiffProcessor::RasterToGTiffProcessor(std::string out_file_full_path,
28 std::string proj_db_path,
29 parser::RasterDataset data,
30 int retry_count)
31 : sapi::Transaction(std::make_unique<GdalSapiSandbox>(
32 sandbox2::file_util::fileops::StripBasename(out_file_full_path),
33 std::move(proj_db_path))),
34 out_file_full_path_(std::move(out_file_full_path)),
35 data_(std::move(data)) {
36 set_retry_count(retry_count);
37 SetTimeLimit(absl::InfiniteDuration());
38 }
39
Main()40 absl::Status RasterToGTiffProcessor::Main() {
41 GdalApi api(sandbox());
42 SAPI_RETURN_IF_ERROR(api.GDALAllRegister());
43
44 sapi::v::CStr driver_name_ptr(kDriverName);
45
46 SAPI_ASSIGN_OR_RETURN(absl::StatusOr<GDALDriverH> driver,
47 api.GDALGetDriverByName(driver_name_ptr.PtrBefore()));
48
49 TRANSACTION_FAIL_IF_NOT(driver.value() != nullptr,
50 "Error getting GTiff driver");
51 sapi::v::RemotePtr driver_ptr(driver.value());
52
53 sapi::v::ConstCStr out_file_full_path_ptr(out_file_full_path_.c_str());
54
55 GDALDataType type = data_.bands.size() > 0
56 ? static_cast<GDALDataType>(data_.bands[0].data_type)
57 : GDALDataType::GDT_Unknown;
58
59 SAPI_ASSIGN_OR_RETURN(
60 absl::StatusOr<GDALDatasetH> dataset,
61 api.GDALCreate(&driver_ptr, out_file_full_path_ptr.PtrBefore(),
62 data_.width, data_.height, data_.bands.size(), type,
63 nullptr));
64
65 TRANSACTION_FAIL_IF_NOT(dataset.value(), "Error creating dataset");
66 sapi::v::RemotePtr dataset_ptr(dataset.value());
67
68 int current_band = 1;
69 for (auto& band_data : data_.bands) {
70 SAPI_ASSIGN_OR_RETURN(absl::StatusOr<GDALRasterBandH> band,
71 api.GDALGetRasterBand(&dataset_ptr, current_band));
72 TRANSACTION_FAIL_IF_NOT(band.value() != nullptr,
73 "Error getting band from dataset");
74 sapi::v::RemotePtr band_ptr(band.value());
75
76 sapi::v::Array<int> data_array(band_data.data.data(),
77 band_data.data.size());
78
79 SAPI_ASSIGN_OR_RETURN(
80 absl::StatusOr<CPLErr> result,
81 api.GDALRasterIO(&band_ptr, GF_Write, 0, 0, band_data.width,
82 band_data.height, data_array.PtrBefore(),
83 band_data.width, band_data.height, GDT_Int32, 0, 0));
84
85 TRANSACTION_FAIL_IF_NOT(result.value() == CPLErr::CE_None,
86 "Error writing band to dataset");
87
88 SAPI_ASSIGN_OR_RETURN(
89 result,
90 api.GDALSetRasterColorInterpretation(
91 &band_ptr, static_cast<GDALColorInterp>(band_data.color_interp)));
92
93 TRANSACTION_FAIL_IF_NOT(result.value() == CPLErr::CE_None,
94 "Error setting color interpretation");
95
96 if (band_data.no_data_value.has_value()) {
97 SAPI_ASSIGN_OR_RETURN(result,
98 api.GDALSetRasterNoDataValue(
99 &band_ptr, band_data.no_data_value.value()));
100
101 TRANSACTION_FAIL_IF_NOT(result.value() == CPLErr::CE_None,
102 "Error setting no data value for the band");
103 }
104
105 ++current_band;
106 }
107
108 if (data_.wkt_projection.length() > 0) {
109 sapi::v::ConstCStr wkt_projection_ptr(data_.wkt_projection.c_str());
110 SAPI_ASSIGN_OR_RETURN(
111 absl::StatusOr<CPLErr> result,
112 api.GDALSetProjection(&dataset_ptr, wkt_projection_ptr.PtrBefore()));
113 TRANSACTION_FAIL_IF_NOT(result.value() == CPLErr::CE_None,
114 "Error setting wkt projection");
115 }
116
117 if (data_.geo_transform.size() > 0) {
118 sapi::v::Array<double> geo_transform_ptr(data_.geo_transform.data(),
119 data_.geo_transform.size());
120 SAPI_ASSIGN_OR_RETURN(
121 absl::StatusOr<CPLErr> result,
122 api.GDALSetGeoTransform(&dataset_ptr, geo_transform_ptr.PtrBefore()));
123
124 TRANSACTION_FAIL_IF_NOT(result.value() == CPLErr::CE_None,
125 "Error setting geo transform");
126 }
127
128 SAPI_RETURN_IF_ERROR(api.GDALClose(&dataset_ptr));
129
130 return absl::OkStatus();
131 }
132
133 } // namespace gdal::sandbox
134