xref: /aosp_15_r20/external/sandboxed-api/oss-internship-2020/gdal/raster_to_gtiff/gtiff_converter.cc (revision ec63e07ab9515d95e79c211197c445ef84cefa6a)
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   sapi::v::NullPtr create_options;
55 
56   GDALDataType type = data_.bands.size() > 0
57                           ? static_cast<GDALDataType>(data_.bands[0].data_type)
58                           : GDALDataType::GDT_Unknown;
59 
60   SAPI_ASSIGN_OR_RETURN(
61       absl::StatusOr<GDALDatasetH> dataset,
62       api.GDALCreate(&driver_ptr, out_file_full_path_ptr.PtrBefore(),
63                      data_.width, data_.height, data_.bands.size(), type,
64                      &create_options));
65 
66   TRANSACTION_FAIL_IF_NOT(dataset.value(), "Error creating dataset");
67   sapi::v::RemotePtr dataset_ptr(dataset.value());
68 
69   int current_band = 1;
70   for (auto& band_data : data_.bands) {
71     SAPI_ASSIGN_OR_RETURN(absl::StatusOr<GDALRasterBandH> band,
72                           api.GDALGetRasterBand(&dataset_ptr, current_band));
73     TRANSACTION_FAIL_IF_NOT(band.value() != nullptr,
74                             "Error getting band from dataset");
75     sapi::v::RemotePtr band_ptr(band.value());
76 
77     sapi::v::Array<int> data_array(band_data.data.data(),
78                                    band_data.data.size());
79 
80     SAPI_ASSIGN_OR_RETURN(
81         absl::StatusOr<CPLErr> result,
82         api.GDALRasterIO(&band_ptr, GF_Write, 0, 0, band_data.width,
83                          band_data.height, data_array.PtrBefore(),
84                          band_data.width, band_data.height, GDT_Int32, 0, 0));
85 
86     TRANSACTION_FAIL_IF_NOT(result.value() == CPLErr::CE_None,
87                             "Error writing band to dataset");
88 
89     SAPI_ASSIGN_OR_RETURN(
90         result,
91         api.GDALSetRasterColorInterpretation(
92             &band_ptr, static_cast<GDALColorInterp>(band_data.color_interp)));
93 
94     TRANSACTION_FAIL_IF_NOT(result.value() == CPLErr::CE_None,
95                             "Error setting color interpretation");
96 
97     if (band_data.no_data_value.has_value()) {
98       SAPI_ASSIGN_OR_RETURN(result,
99                             api.GDALSetRasterNoDataValue(
100                                 &band_ptr, band_data.no_data_value.value()));
101 
102       TRANSACTION_FAIL_IF_NOT(result.value() == CPLErr::CE_None,
103                               "Error setting no data value for the band");
104     }
105 
106     ++current_band;
107   }
108 
109   if (data_.wkt_projection.length() > 0) {
110     sapi::v::ConstCStr wkt_projection_ptr(data_.wkt_projection.c_str());
111     SAPI_ASSIGN_OR_RETURN(
112         absl::StatusOr<CPLErr> result,
113         api.GDALSetProjection(&dataset_ptr, wkt_projection_ptr.PtrBefore()));
114     TRANSACTION_FAIL_IF_NOT(result.value() == CPLErr::CE_None,
115                             "Error setting wkt projection");
116   }
117 
118   if (data_.geo_transform.size() > 0) {
119     sapi::v::Array<double> geo_transform_ptr(data_.geo_transform.data(),
120                                              data_.geo_transform.size());
121     SAPI_ASSIGN_OR_RETURN(
122         absl::StatusOr<CPLErr> result,
123         api.GDALSetGeoTransform(&dataset_ptr, geo_transform_ptr.PtrBefore()));
124 
125     TRANSACTION_FAIL_IF_NOT(result.value() == CPLErr::CE_None,
126                             "Error setting geo transform");
127   }
128 
129   SAPI_RETURN_IF_ERROR(api.GDALClose(&dataset_ptr));
130 
131   return absl::OkStatus();
132 }
133 
134 }  // namespace gdal::sandbox
135