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 "get_raster_data.h" // NOLINT(build/include)
16
17 #include <memory>
18
19 #include "gdal.h" // NOLINT(build/include)
20
21 namespace gdal::sandbox::parser {
22
23 namespace {
24
25 inline constexpr int kGeoTransformSize = 6;
26
27 } // namespace
28
GetRasterBandsFromFile(const std::string & filename)29 RasterDataset GetRasterBandsFromFile(const std::string& filename) {
30 GDALAllRegister();
31 GDALDatasetH dataset = GDALOpen(filename.data(), GA_ReadOnly);
32 GDALDriverH driver = GDALGetDatasetDriver(dataset);
33
34 RasterDataset result_dataset = {GDALGetRasterXSize(dataset),
35 GDALGetRasterYSize(dataset)};
36
37 if (GDALGetProjectionRef(dataset) != nullptr) {
38 result_dataset.wkt_projection = std::string(GDALGetProjectionRef(dataset));
39 }
40
41 std::vector<double> geo_transform(kGeoTransformSize, 0.0);
42
43 if (GDALGetGeoTransform(dataset, geo_transform.data()) == CE_None) {
44 result_dataset.geo_transform = std::move(geo_transform);
45 }
46
47 int bands_count = GDALGetRasterCount(dataset);
48
49 std::vector<RasterBandData> bands_data;
50 bands_data.reserve(bands_count);
51
52 for (int i = 1; i <= bands_count; ++i) {
53 GDALRasterBandH band = GDALGetRasterBand(dataset, i);
54 int width = GDALGetRasterBandXSize(band);
55 int height = GDALGetRasterBandYSize(band);
56
57 std::unique_ptr<int> no_data_result = nullptr;
58 double no_data_value = GDALGetRasterNoDataValue(band, no_data_result.get());
59 std::optional<double> no_data_value_holder =
60 no_data_result.get() == nullptr
61 ? std::nullopt
62 : std::make_optional<double>(no_data_value);
63
64 int data_type = static_cast<int>(GDALGetRasterDataType(band));
65 int color_interp = static_cast<int>(GDALGetRasterColorInterpretation(band));
66
67 std::vector<int32_t> band_raster_data(width * height);
68
69 // GDALRasterIO with GF_Write should use the same type (GDT_Int32)
70 GDALRasterIO(band, GF_Read, 0, 0, width, height, band_raster_data.data(),
71 width, height, GDT_Int32, 0, 0);
72
73 bands_data.push_back({width, height, std::move(band_raster_data), data_type,
74 color_interp, std::move(no_data_value_holder)});
75 }
76
77 result_dataset.bands = std::move(bands_data);
78
79 GDALClose(dataset);
80
81 return result_dataset;
82 }
83
operator ==(const RasterBandData & lhs,const RasterBandData & rhs)84 bool operator==(const RasterBandData& lhs, const RasterBandData& rhs) {
85 return lhs.width == rhs.width && lhs.height == rhs.height &&
86 lhs.data == rhs.data && lhs.data_type == rhs.data_type &&
87 lhs.color_interp == rhs.color_interp &&
88 lhs.no_data_value == rhs.no_data_value;
89 }
90
operator ==(const RasterDataset & lhs,const RasterDataset & rhs)91 bool operator==(const RasterDataset& lhs, const RasterDataset& rhs) {
92 return lhs.width == rhs.width && lhs.height == rhs.height &&
93 lhs.bands == rhs.bands && lhs.wkt_projection == rhs.wkt_projection &&
94 lhs.geo_transform == rhs.geo_transform;
95 }
96
97 } // namespace gdal::sandbox::parser
98