/src/gdal/frmts/raw/hkvdataset.cpp
Line | Count | Source |
1 | | /****************************************************************************** |
2 | | * |
3 | | * Project: GView |
4 | | * Purpose: Implementation of Atlantis HKV labelled blob support |
5 | | * Author: Frank Warmerdam, warmerdam@pobox.com |
6 | | * |
7 | | ****************************************************************************** |
8 | | * Copyright (c) 2000, Frank Warmerdam |
9 | | * Copyright (c) 2008-2012, Even Rouault <even dot rouault at spatialys.com> |
10 | | * |
11 | | * SPDX-License-Identifier: MIT |
12 | | ****************************************************************************/ |
13 | | |
14 | | #include <ctype.h> |
15 | | |
16 | | #include "atlsci_spheroid.h" |
17 | | #include "cpl_string.h" |
18 | | #include "gdal_frmts.h" |
19 | | #include "gdal_priv.h" |
20 | | #include "ogr_spatialref.h" |
21 | | #include "rawdataset.h" |
22 | | |
23 | | #include <cmath> |
24 | | |
25 | | #include <algorithm> |
26 | | |
27 | | /************************************************************************/ |
28 | | /* ==================================================================== */ |
29 | | /* HKVRasterBand */ |
30 | | /* ==================================================================== */ |
31 | | /************************************************************************/ |
32 | | |
33 | | class HKVDataset; |
34 | | |
35 | | class HKVRasterBand final : public RawRasterBand |
36 | | { |
37 | | friend class HKVDataset; |
38 | | |
39 | | public: |
40 | | HKVRasterBand(HKVDataset *poDS, int nBand, VSILFILE *fpRaw, |
41 | | unsigned int nImgOffset, int nPixelOffset, int nLineOffset, |
42 | | GDALDataType eDataType, int bNativeOrder); |
43 | | |
44 | | ~HKVRasterBand() override; |
45 | | }; |
46 | | |
47 | 0 | HKVRasterBand::~HKVRasterBand() = default; |
48 | | |
49 | | /************************************************************************/ |
50 | | /* HKV Spheroids */ |
51 | | /************************************************************************/ |
52 | | |
53 | | class HKVSpheroidList final : public SpheroidList |
54 | | { |
55 | | public: |
56 | | HKVSpheroidList(); |
57 | | }; |
58 | | |
59 | | HKVSpheroidList ::HKVSpheroidList() |
60 | 0 | { |
61 | 0 | num_spheroids = 58; |
62 | 0 | epsilonR = 0.1; |
63 | 0 | epsilonI = 0.000001; |
64 | |
|
65 | 0 | spheroids[0].SetValuesByEqRadiusAndInvFlattening("airy-1830", 6377563.396, |
66 | 0 | 299.3249646); |
67 | 0 | spheroids[1].SetValuesByEqRadiusAndInvFlattening("modified-airy", |
68 | 0 | 6377340.189, 299.3249646); |
69 | 0 | spheroids[2].SetValuesByEqRadiusAndInvFlattening("australian-national", |
70 | 0 | 6378160, 298.25); |
71 | 0 | spheroids[3].SetValuesByEqRadiusAndInvFlattening("bessel-1841-namibia", |
72 | 0 | 6377483.865, 299.1528128); |
73 | 0 | spheroids[4].SetValuesByEqRadiusAndInvFlattening("bessel-1841", 6377397.155, |
74 | 0 | 299.1528128); |
75 | 0 | spheroids[5].SetValuesByEqRadiusAndInvFlattening("clarke-1858", 6378294.0, |
76 | 0 | 294.297); |
77 | 0 | spheroids[6].SetValuesByEqRadiusAndInvFlattening("clarke-1866", 6378206.4, |
78 | 0 | 294.9786982); |
79 | 0 | spheroids[7].SetValuesByEqRadiusAndInvFlattening("clarke-1880", 6378249.145, |
80 | 0 | 293.465); |
81 | 0 | spheroids[8].SetValuesByEqRadiusAndInvFlattening("everest-india-1830", |
82 | 0 | 6377276.345, 300.8017); |
83 | 0 | spheroids[9].SetValuesByEqRadiusAndInvFlattening("everest-sabah-sarawak", |
84 | 0 | 6377298.556, 300.8017); |
85 | 0 | spheroids[10].SetValuesByEqRadiusAndInvFlattening("everest-india-1956", |
86 | 0 | 6377301.243, 300.8017); |
87 | 0 | spheroids[11].SetValuesByEqRadiusAndInvFlattening("everest-malaysia-1969", |
88 | 0 | 6377295.664, 300.8017); |
89 | 0 | spheroids[12].SetValuesByEqRadiusAndInvFlattening("everest-malay-sing", |
90 | 0 | 6377304.063, 300.8017); |
91 | 0 | spheroids[13].SetValuesByEqRadiusAndInvFlattening("everest-pakistan", |
92 | 0 | 6377309.613, 300.8017); |
93 | 0 | spheroids[14].SetValuesByEqRadiusAndInvFlattening("modified-fisher-1960", |
94 | 0 | 6378155, 298.3); |
95 | 0 | spheroids[15].SetValuesByEqRadiusAndInvFlattening("helmert-1906", 6378200, |
96 | 0 | 298.3); |
97 | 0 | spheroids[16].SetValuesByEqRadiusAndInvFlattening("hough-1960", 6378270, |
98 | 0 | 297); |
99 | 0 | spheroids[17].SetValuesByEqRadiusAndInvFlattening("hughes", 6378273.0, |
100 | 0 | 298.279); |
101 | 0 | spheroids[18].SetValuesByEqRadiusAndInvFlattening("indonesian-1974", |
102 | 0 | 6378160, 298.247); |
103 | 0 | spheroids[19].SetValuesByEqRadiusAndInvFlattening("international-1924", |
104 | 0 | 6378388, 297); |
105 | 0 | spheroids[20].SetValuesByEqRadiusAndInvFlattening("iugc-67", 6378160.0, |
106 | 0 | 298.254); |
107 | 0 | spheroids[21].SetValuesByEqRadiusAndInvFlattening("iugc-75", 6378140.0, |
108 | 0 | 298.25298); |
109 | 0 | spheroids[22].SetValuesByEqRadiusAndInvFlattening("krassovsky-1940", |
110 | 0 | 6378245, 298.3); |
111 | 0 | spheroids[23].SetValuesByEqRadiusAndInvFlattening("kaula", 6378165.0, |
112 | 0 | 292.308); |
113 | 0 | spheroids[24].SetValuesByEqRadiusAndInvFlattening("grs-80", 6378137, |
114 | 0 | 298.257222101); |
115 | 0 | spheroids[25].SetValuesByEqRadiusAndInvFlattening("south-american-1969", |
116 | 0 | 6378160, 298.25); |
117 | 0 | spheroids[26].SetValuesByEqRadiusAndInvFlattening("wgs-72", 6378135, |
118 | 0 | 298.26); |
119 | 0 | spheroids[27].SetValuesByEqRadiusAndInvFlattening("wgs-84", 6378137, |
120 | 0 | 298.257223563); |
121 | 0 | spheroids[28].SetValuesByEqRadiusAndInvFlattening("ev-wgs-84", 6378137.0, |
122 | 0 | 298.252841); |
123 | 0 | spheroids[29].SetValuesByEqRadiusAndInvFlattening("ev-bessel", 6377397.0, |
124 | 0 | 299.1976073); |
125 | |
|
126 | 0 | spheroids[30].SetValuesByEqRadiusAndInvFlattening("airy_1830", 6377563.396, |
127 | 0 | 299.3249646); |
128 | 0 | spheroids[31].SetValuesByEqRadiusAndInvFlattening("modified_airy", |
129 | 0 | 6377340.189, 299.3249646); |
130 | 0 | spheroids[32].SetValuesByEqRadiusAndInvFlattening("australian_national", |
131 | 0 | 6378160, 298.25); |
132 | 0 | spheroids[33].SetValuesByEqRadiusAndInvFlattening("bessel_1841_namibia", |
133 | 0 | 6377483.865, 299.1528128); |
134 | 0 | spheroids[34].SetValuesByEqRadiusAndInvFlattening("bessel_1841", |
135 | 0 | 6377397.155, 299.1528128); |
136 | 0 | spheroids[35].SetValuesByEqRadiusAndInvFlattening("clarke_1858", 6378294.0, |
137 | 0 | 294.297); |
138 | 0 | spheroids[36].SetValuesByEqRadiusAndInvFlattening("clarke_1866", 6378206.4, |
139 | 0 | 294.9786982); |
140 | 0 | spheroids[37].SetValuesByEqRadiusAndInvFlattening("clarke_1880", |
141 | 0 | 6378249.145, 293.465); |
142 | 0 | spheroids[38].SetValuesByEqRadiusAndInvFlattening("everest_india_1830", |
143 | 0 | 6377276.345, 300.8017); |
144 | 0 | spheroids[39].SetValuesByEqRadiusAndInvFlattening("everest_sabah_sarawak", |
145 | 0 | 6377298.556, 300.8017); |
146 | 0 | spheroids[40].SetValuesByEqRadiusAndInvFlattening("everest_india_1956", |
147 | 0 | 6377301.243, 300.8017); |
148 | 0 | spheroids[41].SetValuesByEqRadiusAndInvFlattening("everest_malaysia_1969", |
149 | 0 | 6377295.664, 300.8017); |
150 | 0 | spheroids[42].SetValuesByEqRadiusAndInvFlattening("everest_malay_sing", |
151 | 0 | 6377304.063, 300.8017); |
152 | 0 | spheroids[43].SetValuesByEqRadiusAndInvFlattening("everest_pakistan", |
153 | 0 | 6377309.613, 300.8017); |
154 | 0 | spheroids[44].SetValuesByEqRadiusAndInvFlattening("modified_fisher_1960", |
155 | 0 | 6378155, 298.3); |
156 | 0 | spheroids[45].SetValuesByEqRadiusAndInvFlattening("helmert_1906", 6378200, |
157 | 0 | 298.3); |
158 | 0 | spheroids[46].SetValuesByEqRadiusAndInvFlattening("hough_1960", 6378270, |
159 | 0 | 297); |
160 | 0 | spheroids[47].SetValuesByEqRadiusAndInvFlattening("indonesian_1974", |
161 | 0 | 6378160, 298.247); |
162 | 0 | spheroids[48].SetValuesByEqRadiusAndInvFlattening("international_1924", |
163 | 0 | 6378388, 297); |
164 | 0 | spheroids[49].SetValuesByEqRadiusAndInvFlattening("iugc_67", 6378160.0, |
165 | 0 | 298.254); |
166 | 0 | spheroids[50].SetValuesByEqRadiusAndInvFlattening("iugc_75", 6378140.0, |
167 | 0 | 298.25298); |
168 | 0 | spheroids[51].SetValuesByEqRadiusAndInvFlattening("krassovsky_1940", |
169 | 0 | 6378245, 298.3); |
170 | 0 | spheroids[52].SetValuesByEqRadiusAndInvFlattening("grs_80", 6378137, |
171 | 0 | 298.257222101); |
172 | 0 | spheroids[53].SetValuesByEqRadiusAndInvFlattening("south_american_1969", |
173 | 0 | 6378160, 298.25); |
174 | 0 | spheroids[54].SetValuesByEqRadiusAndInvFlattening("wgs_72", 6378135, |
175 | 0 | 298.26); |
176 | 0 | spheroids[55].SetValuesByEqRadiusAndInvFlattening("wgs_84", 6378137, |
177 | 0 | 298.257223563); |
178 | 0 | spheroids[56].SetValuesByEqRadiusAndInvFlattening("ev_wgs_84", 6378137.0, |
179 | 0 | 298.252841); |
180 | 0 | spheroids[57].SetValuesByEqRadiusAndInvFlattening("ev_bessel", 6377397.0, |
181 | 0 | 299.1976073); |
182 | 0 | } |
183 | | |
184 | | /************************************************************************/ |
185 | | /* ==================================================================== */ |
186 | | /* HKVDataset */ |
187 | | /* ==================================================================== */ |
188 | | /************************************************************************/ |
189 | | |
190 | | class HKVDataset final : public RawDataset |
191 | | { |
192 | | friend class HKVRasterBand; |
193 | | |
194 | | char *pszPath; |
195 | | VSILFILE *fpBlob; |
196 | | |
197 | | int nGCPCount; |
198 | | GDAL_GCP *pasGCPList; |
199 | | |
200 | | void ProcessGeoref(const char *); |
201 | | void ProcessGeorefGCP(char **, const char *, double, double); |
202 | | |
203 | | void SetVersion(float version_number) |
204 | 0 | { |
205 | | // Update stored info. |
206 | 0 | MFF2version = version_number; |
207 | 0 | } |
208 | | |
209 | | float MFF2version; |
210 | | |
211 | | GDALDataType eRasterType; |
212 | | |
213 | | void SetNoDataValue(double); |
214 | | |
215 | | OGRSpatialReference m_oSRS{}; |
216 | | OGRSpatialReference m_oGCPSRS{}; |
217 | | GDALGeoTransform m_gt{}; |
218 | | |
219 | | char **papszAttrib; |
220 | | |
221 | | char **papszGeoref; |
222 | | |
223 | | // NOTE: The MFF2 format goes against GDAL's API in that nodata values are |
224 | | // set per-dataset rather than per-band. To compromise, for writing out, |
225 | | // the dataset's nodata value will be set to the last value set on any of |
226 | | // the raster bands. |
227 | | |
228 | | bool bNoDataSet; |
229 | | double dfNoDataValue; |
230 | | |
231 | | CPL_DISALLOW_COPY_ASSIGN(HKVDataset) |
232 | | |
233 | | CPLErr Close(GDALProgressFunc = nullptr, void * = nullptr) override; |
234 | | |
235 | | public: |
236 | | HKVDataset(); |
237 | | ~HKVDataset() override; |
238 | | |
239 | | int GetGCPCount() override /* const */ |
240 | 0 | { |
241 | 0 | return nGCPCount; |
242 | 0 | } |
243 | | |
244 | | const OGRSpatialReference *GetGCPSpatialRef() const override |
245 | 0 | { |
246 | 0 | return m_oGCPSRS.IsEmpty() ? nullptr : &m_oGCPSRS; |
247 | 0 | } |
248 | | |
249 | | const GDAL_GCP *GetGCPs() override; |
250 | | |
251 | | const OGRSpatialReference *GetSpatialRef() const override |
252 | 0 | { |
253 | 0 | return m_oSRS.IsEmpty() ? nullptr : &m_oSRS; |
254 | 0 | } |
255 | | |
256 | | CPLErr GetGeoTransform(GDALGeoTransform &) const override; |
257 | | |
258 | | static GDALDataset *Open(GDALOpenInfo *); |
259 | | }; |
260 | | |
261 | | /************************************************************************/ |
262 | | /* ==================================================================== */ |
263 | | /* HKVRasterBand */ |
264 | | /* ==================================================================== */ |
265 | | /************************************************************************/ |
266 | | |
267 | | /************************************************************************/ |
268 | | /* HKVRasterBand() */ |
269 | | /************************************************************************/ |
270 | | |
271 | | HKVRasterBand::HKVRasterBand(HKVDataset *poDSIn, int nBandIn, VSILFILE *fpRawIn, |
272 | | unsigned int nImgOffsetIn, int nPixelOffsetIn, |
273 | | int nLineOffsetIn, GDALDataType eDataTypeIn, |
274 | | int bNativeOrderIn) |
275 | 0 | : RawRasterBand(GDALDataset::FromHandle(poDSIn), nBandIn, fpRawIn, |
276 | 0 | nImgOffsetIn, nPixelOffsetIn, nLineOffsetIn, eDataTypeIn, |
277 | 0 | bNativeOrderIn, RawRasterBand::OwnFP::NO) |
278 | | |
279 | 0 | { |
280 | 0 | poDS = poDSIn; |
281 | 0 | nBand = nBandIn; |
282 | |
|
283 | 0 | nBlockXSize = poDS->GetRasterXSize(); |
284 | 0 | nBlockYSize = 1; |
285 | 0 | } |
286 | | |
287 | | /************************************************************************/ |
288 | | /* ==================================================================== */ |
289 | | /* HKVDataset */ |
290 | | /* ==================================================================== */ |
291 | | /************************************************************************/ |
292 | | |
293 | | /************************************************************************/ |
294 | | /* HKVDataset() */ |
295 | | /************************************************************************/ |
296 | | |
297 | | HKVDataset::HKVDataset() |
298 | 0 | : pszPath(nullptr), fpBlob(nullptr), nGCPCount(0), pasGCPList(nullptr), |
299 | | // Initialize datasets to new version; change if necessary. |
300 | 0 | MFF2version(1.1f), eRasterType(GDT_Unknown), papszAttrib(nullptr), |
301 | 0 | papszGeoref(nullptr), bNoDataSet(false), dfNoDataValue(0.0) |
302 | 0 | { |
303 | 0 | m_oSRS.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER); |
304 | 0 | m_oGCPSRS.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER); |
305 | 0 | } |
306 | | |
307 | | /************************************************************************/ |
308 | | /* ~HKVDataset() */ |
309 | | /************************************************************************/ |
310 | | |
311 | | HKVDataset::~HKVDataset() |
312 | | |
313 | 0 | { |
314 | 0 | HKVDataset::Close(); |
315 | 0 | } |
316 | | |
317 | | /************************************************************************/ |
318 | | /* Close() */ |
319 | | /************************************************************************/ |
320 | | |
321 | | CPLErr HKVDataset::Close(GDALProgressFunc, void *) |
322 | 0 | { |
323 | 0 | CPLErr eErr = CE_None; |
324 | 0 | if (nOpenFlags != OPEN_FLAGS_CLOSED) |
325 | 0 | { |
326 | 0 | if (HKVDataset::FlushCache(true) != CE_None) |
327 | 0 | eErr = CE_Failure; |
328 | |
|
329 | 0 | if (fpBlob) |
330 | 0 | { |
331 | 0 | if (VSIFCloseL(fpBlob) != 0) |
332 | 0 | { |
333 | 0 | eErr = CE_Failure; |
334 | 0 | CPLError(CE_Failure, CPLE_FileIO, "I/O error"); |
335 | 0 | } |
336 | 0 | } |
337 | |
|
338 | 0 | if (nGCPCount > 0) |
339 | 0 | { |
340 | 0 | GDALDeinitGCPs(nGCPCount, pasGCPList); |
341 | 0 | CPLFree(pasGCPList); |
342 | 0 | } |
343 | |
|
344 | 0 | CPLFree(pszPath); |
345 | 0 | CSLDestroy(papszGeoref); |
346 | 0 | CSLDestroy(papszAttrib); |
347 | |
|
348 | 0 | if (GDALPamDataset::Close() != CE_None) |
349 | 0 | eErr = CE_Failure; |
350 | 0 | } |
351 | 0 | return eErr; |
352 | 0 | } |
353 | | |
354 | | /************************************************************************/ |
355 | | /* GetGeoTransform() */ |
356 | | /************************************************************************/ |
357 | | |
358 | | CPLErr HKVDataset::GetGeoTransform(GDALGeoTransform >) const |
359 | | |
360 | 0 | { |
361 | 0 | gt = m_gt; |
362 | 0 | return CE_None; |
363 | 0 | } |
364 | | |
365 | | /************************************************************************/ |
366 | | /* GetGCP() */ |
367 | | /************************************************************************/ |
368 | | |
369 | | const GDAL_GCP *HKVDataset::GetGCPs() |
370 | | |
371 | 0 | { |
372 | 0 | return pasGCPList; |
373 | 0 | } |
374 | | |
375 | | /************************************************************************/ |
376 | | /* ProcessGeorefGCP() */ |
377 | | /************************************************************************/ |
378 | | |
379 | | void HKVDataset::ProcessGeorefGCP(char **papszGeorefIn, const char *pszBase, |
380 | | double dfRasterX, double dfRasterY) |
381 | | |
382 | 0 | { |
383 | | /* -------------------------------------------------------------------- */ |
384 | | /* Fetch the GCP from the string list. */ |
385 | | /* -------------------------------------------------------------------- */ |
386 | 0 | char szFieldName[128] = {'\0'}; |
387 | 0 | snprintf(szFieldName, sizeof(szFieldName), "%s.latitude", pszBase); |
388 | 0 | double dfLat = 0.0; |
389 | 0 | if (CSLFetchNameValue(papszGeorefIn, szFieldName) == nullptr) |
390 | 0 | return; |
391 | 0 | else |
392 | 0 | dfLat = CPLAtof(CSLFetchNameValue(papszGeorefIn, szFieldName)); |
393 | | |
394 | 0 | snprintf(szFieldName, sizeof(szFieldName), "%s.longitude", pszBase); |
395 | 0 | double dfLong = 0.0; |
396 | 0 | if (CSLFetchNameValue(papszGeorefIn, szFieldName) == nullptr) |
397 | 0 | return; |
398 | 0 | else |
399 | 0 | dfLong = CPLAtof(CSLFetchNameValue(papszGeorefIn, szFieldName)); |
400 | | |
401 | | /* -------------------------------------------------------------------- */ |
402 | | /* Add the gcp to the internal list. */ |
403 | | /* -------------------------------------------------------------------- */ |
404 | 0 | GDALInitGCPs(1, pasGCPList + nGCPCount); |
405 | |
|
406 | 0 | CPLFree(pasGCPList[nGCPCount].pszId); |
407 | |
|
408 | 0 | pasGCPList[nGCPCount].pszId = CPLStrdup(pszBase); |
409 | |
|
410 | 0 | pasGCPList[nGCPCount].dfGCPX = dfLong; |
411 | 0 | pasGCPList[nGCPCount].dfGCPY = dfLat; |
412 | 0 | pasGCPList[nGCPCount].dfGCPZ = 0.0; |
413 | |
|
414 | 0 | pasGCPList[nGCPCount].dfGCPPixel = dfRasterX; |
415 | 0 | pasGCPList[nGCPCount].dfGCPLine = dfRasterY; |
416 | |
|
417 | 0 | nGCPCount++; |
418 | 0 | } |
419 | | |
420 | | /************************************************************************/ |
421 | | /* ProcessGeoref() */ |
422 | | /************************************************************************/ |
423 | | |
424 | | void HKVDataset::ProcessGeoref(const char *pszFilename) |
425 | | |
426 | 0 | { |
427 | | /* -------------------------------------------------------------------- */ |
428 | | /* Load the georef file, and boil white space away from around */ |
429 | | /* the equal sign. */ |
430 | | /* -------------------------------------------------------------------- */ |
431 | 0 | CSLDestroy(papszGeoref); |
432 | 0 | papszGeoref = CSLLoad(pszFilename); |
433 | 0 | if (papszGeoref == nullptr) |
434 | 0 | return; |
435 | | |
436 | 0 | HKVSpheroidList *hkvEllipsoids = new HKVSpheroidList; |
437 | |
|
438 | 0 | for (int i = 0; papszGeoref[i] != nullptr; i++) |
439 | 0 | { |
440 | 0 | int iDst = 0; |
441 | 0 | char *pszLine = papszGeoref[i]; |
442 | |
|
443 | 0 | for (int iSrc = 0; pszLine[iSrc] != '\0'; iSrc++) |
444 | 0 | { |
445 | 0 | if (pszLine[iSrc] != ' ') |
446 | 0 | { |
447 | 0 | pszLine[iDst++] = pszLine[iSrc]; |
448 | 0 | } |
449 | 0 | } |
450 | 0 | pszLine[iDst] = '\0'; |
451 | 0 | } |
452 | | |
453 | | /* -------------------------------------------------------------------- */ |
454 | | /* Try to get GCPs, in lat/longs . */ |
455 | | /* -------------------------------------------------------------------- */ |
456 | 0 | nGCPCount = 0; |
457 | 0 | pasGCPList = static_cast<GDAL_GCP *>(CPLCalloc(sizeof(GDAL_GCP), 5)); |
458 | |
|
459 | 0 | if (MFF2version > 1.0) |
460 | 0 | { |
461 | 0 | ProcessGeorefGCP(papszGeoref, "top_left", 0, 0); |
462 | 0 | ProcessGeorefGCP(papszGeoref, "top_right", GetRasterXSize(), 0); |
463 | 0 | ProcessGeorefGCP(papszGeoref, "bottom_left", 0, GetRasterYSize()); |
464 | 0 | ProcessGeorefGCP(papszGeoref, "bottom_right", GetRasterXSize(), |
465 | 0 | GetRasterYSize()); |
466 | 0 | ProcessGeorefGCP(papszGeoref, "centre", GetRasterXSize() / 2.0, |
467 | 0 | GetRasterYSize() / 2.0); |
468 | 0 | } |
469 | 0 | else |
470 | 0 | { |
471 | 0 | ProcessGeorefGCP(papszGeoref, "top_left", 0.5, 0.5); |
472 | 0 | ProcessGeorefGCP(papszGeoref, "top_right", GetRasterXSize() - 0.5, 0.5); |
473 | 0 | ProcessGeorefGCP(papszGeoref, "bottom_left", 0.5, |
474 | 0 | GetRasterYSize() - 0.5); |
475 | 0 | ProcessGeorefGCP(papszGeoref, "bottom_right", GetRasterXSize() - 0.5, |
476 | 0 | GetRasterYSize() - 0.5); |
477 | 0 | ProcessGeorefGCP(papszGeoref, "centre", GetRasterXSize() / 2.0, |
478 | 0 | GetRasterYSize() / 2.0); |
479 | 0 | } |
480 | |
|
481 | 0 | if (nGCPCount == 0) |
482 | 0 | { |
483 | 0 | CPLFree(pasGCPList); |
484 | 0 | pasGCPList = nullptr; |
485 | 0 | } |
486 | | |
487 | | /* -------------------------------------------------------------------- */ |
488 | | /* Do we have a recognised projection? */ |
489 | | /* -------------------------------------------------------------------- */ |
490 | 0 | const char *pszProjName = CSLFetchNameValue(papszGeoref, "projection.name"); |
491 | 0 | const char *pszOriginLong = |
492 | 0 | CSLFetchNameValue(papszGeoref, "projection.origin_longitude"); |
493 | 0 | const char *pszSpheroidName = |
494 | 0 | CSLFetchNameValue(papszGeoref, "spheroid.name"); |
495 | |
|
496 | 0 | if (pszSpheroidName != nullptr && |
497 | 0 | hkvEllipsoids->SpheroidInList(pszSpheroidName)) |
498 | 0 | { |
499 | | #if 0 |
500 | | // TODO(schwehr): Enable in trunk after 2.1 branch and fix. |
501 | | // Breaks tests on some platforms. |
502 | | CPLError( CE_Failure, CPLE_AppDefined, |
503 | | "Unrecognized ellipsoid. Not handled. " |
504 | | "Spheroid name not in spheroid list: '%s'", |
505 | | pszSpheroidName ); |
506 | | #endif |
507 | | // Why were eq_radius and inv_flattening never used? |
508 | | // eq_radius = hkvEllipsoids->GetSpheroidEqRadius(pszSpheroidName); |
509 | | // inv_flattening = |
510 | | // hkvEllipsoids->GetSpheroidInverseFlattening(pszSpheroidName); |
511 | 0 | } |
512 | 0 | else if (pszProjName != nullptr) |
513 | 0 | { |
514 | 0 | CPLError(CE_Warning, CPLE_AppDefined, |
515 | 0 | "Unrecognized ellipsoid. Not handled."); |
516 | | // TODO(schwehr): This error is was never what was happening. |
517 | | // CPLError( CE_Warning, CPLE_AppDefined, |
518 | | // "Unrecognized ellipsoid. Using wgs-84 parameters."); |
519 | | // eq_radius=hkvEllipsoids->GetSpheroidEqRadius("wgs-84"); */ |
520 | | // inv_flattening=hkvEllipsoids->GetSpheroidInverseFlattening("wgs-84"); |
521 | 0 | } |
522 | |
|
523 | 0 | if (pszProjName != nullptr && EQUAL(pszProjName, "utm") && nGCPCount == 5) |
524 | 0 | { |
525 | | // int nZone = (int)((CPLAtof(pszOriginLong)+184.5) / 6.0); |
526 | 0 | int nZone = 31; // TODO(schwehr): Where does 31 come from? |
527 | |
|
528 | 0 | if (pszOriginLong == nullptr) |
529 | 0 | { |
530 | | // If origin not specified, assume 0.0. |
531 | 0 | CPLError( |
532 | 0 | CE_Warning, CPLE_AppDefined, |
533 | 0 | "No projection origin longitude specified. Assuming 0.0."); |
534 | 0 | } |
535 | 0 | else |
536 | 0 | { |
537 | 0 | nZone = 31 + static_cast<int>(floor(CPLAtof(pszOriginLong) / 6.0)); |
538 | 0 | } |
539 | |
|
540 | 0 | OGRSpatialReference oUTM; |
541 | |
|
542 | 0 | if (pasGCPList[4].dfGCPY < 0) |
543 | 0 | oUTM.SetUTM(nZone, 0); |
544 | 0 | else |
545 | 0 | oUTM.SetUTM(nZone, 1); |
546 | |
|
547 | 0 | OGRSpatialReference oLL; |
548 | 0 | oLL.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER); |
549 | 0 | if (pszOriginLong != nullptr) |
550 | 0 | { |
551 | 0 | oUTM.SetProjParm(SRS_PP_CENTRAL_MERIDIAN, CPLAtof(pszOriginLong)); |
552 | 0 | oLL.SetProjParm(SRS_PP_LONGITUDE_OF_ORIGIN, CPLAtof(pszOriginLong)); |
553 | 0 | } |
554 | |
|
555 | 0 | if ((pszSpheroidName == nullptr) || |
556 | 0 | (EQUAL(pszSpheroidName, "wgs-84")) || |
557 | 0 | (EQUAL(pszSpheroidName, "wgs_84"))) |
558 | 0 | { |
559 | 0 | oUTM.SetWellKnownGeogCS("WGS84"); |
560 | 0 | oLL.SetWellKnownGeogCS("WGS84"); |
561 | 0 | } |
562 | 0 | else |
563 | 0 | { |
564 | 0 | if (hkvEllipsoids->SpheroidInList(pszSpheroidName)) |
565 | 0 | { |
566 | 0 | oUTM.SetGeogCS( |
567 | 0 | "unknown", "unknown", pszSpheroidName, |
568 | 0 | hkvEllipsoids->GetSpheroidEqRadius(pszSpheroidName), |
569 | 0 | hkvEllipsoids->GetSpheroidInverseFlattening( |
570 | 0 | pszSpheroidName)); |
571 | 0 | oLL.SetGeogCS( |
572 | 0 | "unknown", "unknown", pszSpheroidName, |
573 | 0 | hkvEllipsoids->GetSpheroidEqRadius(pszSpheroidName), |
574 | 0 | hkvEllipsoids->GetSpheroidInverseFlattening( |
575 | 0 | pszSpheroidName)); |
576 | 0 | } |
577 | 0 | else |
578 | 0 | { |
579 | 0 | CPLError(CE_Warning, CPLE_AppDefined, |
580 | 0 | "Unrecognized ellipsoid. Using wgs-84 parameters."); |
581 | 0 | oUTM.SetWellKnownGeogCS("WGS84"); |
582 | 0 | oLL.SetWellKnownGeogCS("WGS84"); |
583 | 0 | } |
584 | 0 | } |
585 | |
|
586 | 0 | OGRCoordinateTransformation *poTransform = |
587 | 0 | OGRCreateCoordinateTransformation(&oLL, &oUTM); |
588 | |
|
589 | 0 | bool bSuccess = true; |
590 | 0 | if (poTransform == nullptr) |
591 | 0 | { |
592 | 0 | CPLErrorReset(); |
593 | 0 | bSuccess = false; |
594 | 0 | } |
595 | |
|
596 | 0 | double dfUtmX[5] = {0.0}; |
597 | 0 | double dfUtmY[5] = {0.0}; |
598 | |
|
599 | 0 | if (poTransform != nullptr) |
600 | 0 | { |
601 | 0 | for (int gcp_index = 0; gcp_index < 5; gcp_index++) |
602 | 0 | { |
603 | 0 | dfUtmX[gcp_index] = pasGCPList[gcp_index].dfGCPX; |
604 | 0 | dfUtmY[gcp_index] = pasGCPList[gcp_index].dfGCPY; |
605 | |
|
606 | 0 | if (bSuccess && !poTransform->Transform(1, &(dfUtmX[gcp_index]), |
607 | 0 | &(dfUtmY[gcp_index]))) |
608 | 0 | bSuccess = false; |
609 | 0 | } |
610 | 0 | } |
611 | |
|
612 | 0 | if (bSuccess) |
613 | 0 | { |
614 | | // Update GCPS to proper projection. |
615 | 0 | for (int gcp_index = 0; gcp_index < 5; gcp_index++) |
616 | 0 | { |
617 | 0 | pasGCPList[gcp_index].dfGCPX = dfUtmX[gcp_index]; |
618 | 0 | pasGCPList[gcp_index].dfGCPY = dfUtmY[gcp_index]; |
619 | 0 | } |
620 | |
|
621 | 0 | m_oGCPSRS = oUTM; |
622 | |
|
623 | 0 | bool transform_ok = CPL_TO_BOOL( |
624 | 0 | GDALGCPsToGeoTransform(5, pasGCPList, m_gt.data(), 0)); |
625 | |
|
626 | 0 | if (!transform_ok) |
627 | 0 | { |
628 | | // Transform may not be sufficient in all cases (slant range |
629 | | // projection). |
630 | 0 | m_gt = GDALGeoTransform(); |
631 | 0 | m_oGCPSRS.Clear(); |
632 | 0 | } |
633 | 0 | else |
634 | 0 | { |
635 | 0 | m_oSRS = std::move(oUTM); |
636 | 0 | } |
637 | 0 | } |
638 | |
|
639 | 0 | if (poTransform != nullptr) |
640 | 0 | delete poTransform; |
641 | 0 | } |
642 | 0 | else if (pszProjName != nullptr && nGCPCount == 5) |
643 | 0 | { |
644 | 0 | OGRSpatialReference oLL; |
645 | 0 | oLL.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER); |
646 | |
|
647 | 0 | if (pszOriginLong != nullptr) |
648 | 0 | { |
649 | 0 | oLL.SetProjParm(SRS_PP_LONGITUDE_OF_ORIGIN, CPLAtof(pszOriginLong)); |
650 | 0 | } |
651 | |
|
652 | 0 | if (pszSpheroidName == nullptr || |
653 | 0 | EQUAL(pszSpheroidName, "wgs-84") || // Dash. |
654 | 0 | EQUAL(pszSpheroidName, "wgs_84")) // Underscore. |
655 | 0 | { |
656 | 0 | oLL.SetWellKnownGeogCS("WGS84"); |
657 | 0 | } |
658 | 0 | else |
659 | 0 | { |
660 | 0 | if (hkvEllipsoids->SpheroidInList(pszSpheroidName)) |
661 | 0 | { |
662 | 0 | oLL.SetGeogCS( |
663 | 0 | "", "", pszSpheroidName, |
664 | 0 | hkvEllipsoids->GetSpheroidEqRadius(pszSpheroidName), |
665 | 0 | hkvEllipsoids->GetSpheroidInverseFlattening( |
666 | 0 | pszSpheroidName)); |
667 | 0 | } |
668 | 0 | else |
669 | 0 | { |
670 | 0 | CPLError(CE_Warning, CPLE_AppDefined, |
671 | 0 | "Unrecognized ellipsoid. " |
672 | 0 | "Using wgs-84 parameters."); |
673 | 0 | oLL.SetWellKnownGeogCS("WGS84"); |
674 | 0 | } |
675 | 0 | } |
676 | |
|
677 | 0 | const bool transform_ok = |
678 | 0 | CPL_TO_BOOL(GDALGCPsToGeoTransform(5, pasGCPList, m_gt.data(), 0)); |
679 | |
|
680 | 0 | m_oSRS.Clear(); |
681 | |
|
682 | 0 | if (!transform_ok) |
683 | 0 | { |
684 | 0 | m_gt = GDALGeoTransform(); |
685 | 0 | } |
686 | 0 | else |
687 | 0 | { |
688 | 0 | m_oSRS = oLL; |
689 | 0 | } |
690 | |
|
691 | 0 | m_oGCPSRS = std::move(oLL); |
692 | 0 | } |
693 | |
|
694 | 0 | delete hkvEllipsoids; |
695 | 0 | } |
696 | | |
697 | | /************************************************************************/ |
698 | | /* Open() */ |
699 | | /************************************************************************/ |
700 | | |
701 | | GDALDataset *HKVDataset::Open(GDALOpenInfo *poOpenInfo) |
702 | | |
703 | 467k | { |
704 | | /* -------------------------------------------------------------------- */ |
705 | | /* We assume the dataset is passed as a directory. Check for */ |
706 | | /* an attrib and blob file as a minimum. */ |
707 | | /* -------------------------------------------------------------------- */ |
708 | 467k | if (!poOpenInfo->bIsDirectory) |
709 | 464k | return nullptr; |
710 | | |
711 | 3.62k | std::string osFilename = |
712 | 3.62k | CPLFormFilenameSafe(poOpenInfo->pszFilename, "image_data", nullptr); |
713 | 3.62k | VSIStatBuf sStat; |
714 | 3.62k | if (VSIStat(osFilename.c_str(), &sStat) != 0) |
715 | 3.62k | osFilename = |
716 | 3.62k | CPLFormFilenameSafe(poOpenInfo->pszFilename, "blob", nullptr); |
717 | 3.62k | if (VSIStat(osFilename.c_str(), &sStat) != 0) |
718 | 3.62k | return nullptr; |
719 | | |
720 | 0 | osFilename = |
721 | 0 | CPLFormFilenameSafe(poOpenInfo->pszFilename, "attrib", nullptr); |
722 | 0 | if (VSIStat(osFilename.c_str(), &sStat) != 0) |
723 | 0 | return nullptr; |
724 | | |
725 | | /* -------------------------------------------------------------------- */ |
726 | | /* Load the attrib file, and boil white space away from around */ |
727 | | /* the equal sign. */ |
728 | | /* -------------------------------------------------------------------- */ |
729 | 0 | char **papszAttrib = CSLLoad(osFilename.c_str()); |
730 | 0 | if (papszAttrib == nullptr) |
731 | 0 | return nullptr; |
732 | | |
733 | 0 | for (int i = 0; papszAttrib[i] != nullptr; i++) |
734 | 0 | { |
735 | 0 | int iDst = 0; |
736 | 0 | char *pszLine = papszAttrib[i]; |
737 | |
|
738 | 0 | for (int iSrc = 0; pszLine[iSrc] != '\0'; iSrc++) |
739 | 0 | { |
740 | 0 | if (pszLine[iSrc] != ' ') |
741 | 0 | { |
742 | 0 | pszLine[iDst++] = pszLine[iSrc]; |
743 | 0 | } |
744 | 0 | } |
745 | 0 | pszLine[iDst] = '\0'; |
746 | 0 | } |
747 | | |
748 | | /* -------------------------------------------------------------------- */ |
749 | | /* Create a corresponding GDALDataset. */ |
750 | | /* -------------------------------------------------------------------- */ |
751 | 0 | auto poDS = std::make_unique<HKVDataset>(); |
752 | |
|
753 | 0 | poDS->pszPath = CPLStrdup(poOpenInfo->pszFilename); |
754 | 0 | poDS->papszAttrib = papszAttrib; |
755 | |
|
756 | 0 | poDS->eAccess = poOpenInfo->eAccess; |
757 | | |
758 | | /* -------------------------------------------------------------------- */ |
759 | | /* Set some dataset wide information. */ |
760 | | /* -------------------------------------------------------------------- */ |
761 | 0 | bool bNative = false; |
762 | 0 | bool bComplex = false; |
763 | 0 | int nRawBands = 0; |
764 | |
|
765 | 0 | if (CSLFetchNameValue(papszAttrib, "extent.cols") == nullptr || |
766 | 0 | CSLFetchNameValue(papszAttrib, "extent.rows") == nullptr) |
767 | 0 | { |
768 | 0 | return nullptr; |
769 | 0 | } |
770 | | |
771 | 0 | poDS->nRasterXSize = atoi(CSLFetchNameValue(papszAttrib, "extent.cols")); |
772 | 0 | poDS->nRasterYSize = atoi(CSLFetchNameValue(papszAttrib, "extent.rows")); |
773 | |
|
774 | 0 | if (!GDALCheckDatasetDimensions(poDS->nRasterXSize, poDS->nRasterYSize)) |
775 | 0 | { |
776 | 0 | return nullptr; |
777 | 0 | } |
778 | | |
779 | 0 | const char *pszValue = CSLFetchNameValue(papszAttrib, "pixel.order"); |
780 | 0 | if (pszValue == nullptr) |
781 | 0 | bNative = true; |
782 | 0 | else |
783 | 0 | { |
784 | | #ifdef CPL_MSB |
785 | | bNative = strstr(pszValue, "*msbf") != NULL; |
786 | | #else |
787 | 0 | bNative = strstr(pszValue, "*lsbf") != nullptr; |
788 | 0 | #endif |
789 | 0 | } |
790 | |
|
791 | 0 | bool bNoDataSet = false; |
792 | 0 | double dfNoDataValue = 0.0; |
793 | 0 | pszValue = CSLFetchNameValue(papszAttrib, "pixel.no_data"); |
794 | 0 | if (pszValue != nullptr) |
795 | 0 | { |
796 | 0 | bNoDataSet = true; |
797 | 0 | dfNoDataValue = CPLAtof(pszValue); |
798 | 0 | } |
799 | |
|
800 | 0 | pszValue = CSLFetchNameValue(papszAttrib, "channel.enumeration"); |
801 | 0 | if (pszValue != nullptr) |
802 | 0 | nRawBands = atoi(pszValue); |
803 | 0 | else |
804 | 0 | nRawBands = 1; |
805 | |
|
806 | 0 | if (!GDALCheckBandCount(nRawBands, TRUE)) |
807 | 0 | { |
808 | 0 | return nullptr; |
809 | 0 | } |
810 | | |
811 | 0 | pszValue = CSLFetchNameValue(papszAttrib, "pixel.field"); |
812 | 0 | if (pszValue != nullptr && strstr(pszValue, "*complex") != nullptr) |
813 | 0 | bComplex = true; |
814 | 0 | else |
815 | 0 | bComplex = false; |
816 | | |
817 | | /* Get the version number, if present (if not, assume old version. */ |
818 | | /* Versions differ in their interpretation of corner coordinates. */ |
819 | |
|
820 | 0 | if (CSLFetchNameValue(papszAttrib, "version") != nullptr) |
821 | 0 | poDS->SetVersion(static_cast<float>( |
822 | 0 | CPLAtof(CSLFetchNameValue(papszAttrib, "version")))); |
823 | 0 | else |
824 | 0 | poDS->SetVersion(1.0); |
825 | | |
826 | | /* -------------------------------------------------------------------- */ |
827 | | /* Figure out the datatype */ |
828 | | /* -------------------------------------------------------------------- */ |
829 | 0 | const char *pszEncoding = CSLFetchNameValue(papszAttrib, "pixel.encoding"); |
830 | 0 | if (pszEncoding == nullptr) |
831 | 0 | pszEncoding = "{ *unsigned }"; |
832 | |
|
833 | 0 | int nSize = 1; |
834 | 0 | if (CSLFetchNameValue(papszAttrib, "pixel.size") != nullptr) |
835 | 0 | nSize = atoi(CSLFetchNameValue(papszAttrib, "pixel.size")) / 8; |
836 | | #if 0 |
837 | | int nPseudoBands; |
838 | | if( bComplex ) |
839 | | nPseudoBands = 2; |
840 | | else |
841 | | nPseudoBands = 1; |
842 | | #endif |
843 | |
|
844 | 0 | GDALDataType eType; |
845 | 0 | if (nSize == 1) |
846 | 0 | eType = GDT_UInt8; |
847 | 0 | else if (nSize == 2 && strstr(pszEncoding, "*unsigned") != nullptr) |
848 | 0 | eType = GDT_UInt16; |
849 | 0 | else if (nSize == 4 && bComplex) |
850 | 0 | eType = GDT_CInt16; |
851 | 0 | else if (nSize == 2) |
852 | 0 | eType = GDT_Int16; |
853 | 0 | else if (nSize == 4 && strstr(pszEncoding, "*unsigned") != nullptr) |
854 | 0 | eType = GDT_UInt32; |
855 | 0 | else if (nSize == 8 && strstr(pszEncoding, "*two") != nullptr && bComplex) |
856 | 0 | eType = GDT_CInt32; |
857 | 0 | else if (nSize == 4 && strstr(pszEncoding, "*two") != nullptr) |
858 | 0 | eType = GDT_Int32; |
859 | 0 | else if (nSize == 8 && bComplex) |
860 | 0 | eType = GDT_CFloat32; |
861 | 0 | else if (nSize == 4) |
862 | 0 | eType = GDT_Float32; |
863 | 0 | else if (nSize == 16 && bComplex) |
864 | 0 | eType = GDT_CFloat64; |
865 | 0 | else if (nSize == 8) |
866 | 0 | eType = GDT_Float64; |
867 | 0 | else |
868 | 0 | { |
869 | 0 | CPLError(CE_Failure, CPLE_AppDefined, |
870 | 0 | "Unsupported pixel data type in %s.\n" |
871 | 0 | "pixel.size=%d pixel.encoding=%s", |
872 | 0 | poDS->pszPath, nSize, pszEncoding); |
873 | 0 | return nullptr; |
874 | 0 | } |
875 | | |
876 | | /* -------------------------------------------------------------------- */ |
877 | | /* Open the blob file. */ |
878 | | /* -------------------------------------------------------------------- */ |
879 | 0 | osFilename = CPLFormFilenameSafe(poDS->pszPath, "image_data", nullptr); |
880 | 0 | if (VSIStat(osFilename.c_str(), &sStat) != 0) |
881 | 0 | osFilename = CPLFormFilenameSafe(poDS->pszPath, "blob", nullptr); |
882 | 0 | if (poOpenInfo->eAccess == GA_ReadOnly) |
883 | 0 | { |
884 | 0 | poDS->fpBlob = VSIFOpenL(osFilename.c_str(), "rb"); |
885 | 0 | if (poDS->fpBlob == nullptr) |
886 | 0 | { |
887 | 0 | CPLError(CE_Failure, CPLE_OpenFailed, |
888 | 0 | "Unable to open file %s for read access.", |
889 | 0 | osFilename.c_str()); |
890 | 0 | return nullptr; |
891 | 0 | } |
892 | 0 | } |
893 | 0 | else |
894 | 0 | { |
895 | 0 | poDS->fpBlob = VSIFOpenL(osFilename.c_str(), "rb+"); |
896 | 0 | if (poDS->fpBlob == nullptr) |
897 | 0 | { |
898 | 0 | CPLError(CE_Failure, CPLE_OpenFailed, |
899 | 0 | "Unable to open file %s for update access.", |
900 | 0 | osFilename.c_str()); |
901 | 0 | return nullptr; |
902 | 0 | } |
903 | 0 | } |
904 | | |
905 | | /* -------------------------------------------------------------------- */ |
906 | | /* Build the overview filename, as blob file = "_ovr". */ |
907 | | /* -------------------------------------------------------------------- */ |
908 | 0 | std::string osOvrFilename(osFilename); |
909 | 0 | osOvrFilename += "_ovr"; |
910 | | |
911 | | /* -------------------------------------------------------------------- */ |
912 | | /* Define the bands. */ |
913 | | /* -------------------------------------------------------------------- */ |
914 | 0 | const int nPixelOffset = nRawBands * nSize; |
915 | 0 | const int nLineOffset = nPixelOffset * poDS->GetRasterXSize(); |
916 | 0 | int nOffset = 0; |
917 | |
|
918 | 0 | for (int iRawBand = 0; iRawBand < nRawBands; iRawBand++) |
919 | 0 | { |
920 | 0 | auto poBand = std::make_unique<HKVRasterBand>( |
921 | 0 | poDS.get(), poDS->GetRasterCount() + 1, poDS->fpBlob, nOffset, |
922 | 0 | nPixelOffset, nLineOffset, eType, bNative); |
923 | 0 | if (!poBand->IsValid()) |
924 | 0 | return nullptr; |
925 | | |
926 | 0 | if (bNoDataSet) |
927 | 0 | poBand->SetNoDataValue(dfNoDataValue); |
928 | 0 | poDS->SetBand(poDS->GetRasterCount() + 1, std::move(poBand)); |
929 | 0 | nOffset += GDALGetDataTypeSizeBytes(eType); |
930 | 0 | } |
931 | | |
932 | 0 | poDS->eRasterType = eType; |
933 | | |
934 | | /* -------------------------------------------------------------------- */ |
935 | | /* Process the georef file if there is one. */ |
936 | | /* -------------------------------------------------------------------- */ |
937 | 0 | osFilename = CPLFormFilenameSafe(poDS->pszPath, "georef", nullptr); |
938 | 0 | if (VSIStat(osFilename.c_str(), &sStat) == 0) |
939 | 0 | poDS->ProcessGeoref(osFilename.c_str()); |
940 | | |
941 | | /* -------------------------------------------------------------------- */ |
942 | | /* Initialize any PAM information. */ |
943 | | /* -------------------------------------------------------------------- */ |
944 | 0 | poDS->SetDescription(osOvrFilename.c_str()); |
945 | 0 | poDS->TryLoadXML(); |
946 | | |
947 | | /* -------------------------------------------------------------------- */ |
948 | | /* Handle overviews. */ |
949 | | /* -------------------------------------------------------------------- */ |
950 | 0 | poDS->oOvManager.Initialize(poDS.get(), osOvrFilename.c_str(), nullptr, |
951 | 0 | TRUE); |
952 | |
|
953 | 0 | return poDS.release(); |
954 | 0 | } |
955 | | |
956 | | /************************************************************************/ |
957 | | /* GDALRegister_HKV() */ |
958 | | /************************************************************************/ |
959 | | |
960 | | void GDALRegister_HKV() |
961 | | |
962 | 22 | { |
963 | 22 | if (GDALGetDriverByName("MFF2") != nullptr) |
964 | 0 | return; |
965 | | |
966 | 22 | GDALDriver *poDriver = new GDALDriver(); |
967 | | |
968 | 22 | poDriver->SetDescription("MFF2"); |
969 | 22 | poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES"); |
970 | 22 | poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "Vexcel MFF2 (HKV) Raster"); |
971 | 22 | poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/raster/mff2.html"); |
972 | | |
973 | 22 | poDriver->pfnOpen = HKVDataset::Open; |
974 | | |
975 | 22 | GetGDALDriverManager()->RegisterDriver(poDriver); |
976 | 22 | } |