/src/gdal/frmts/raw/byndataset.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /****************************************************************************** |
2 | | * |
3 | | * Project: Natural Resources Canada's Geoid BYN file format |
4 | | * Purpose: Implementation of BYN format |
5 | | * Author: Ivan Lucena, ivan.lucena@outlook.com |
6 | | * |
7 | | ****************************************************************************** |
8 | | * Copyright (c) 2018, Ivan Lucena |
9 | | * Copyright (c) 2018, Even Rouault |
10 | | * |
11 | | * SPDX-License-Identifier: MIT |
12 | | ****************************************************************************/ |
13 | | |
14 | | #include "cpl_port.h" |
15 | | #include "byndataset.h" |
16 | | #include "rawdataset.h" |
17 | | |
18 | | #include "cpl_string.h" |
19 | | #include "gdal_frmts.h" |
20 | | #include "ogr_spatialref.h" |
21 | | #include "ogr_srs_api.h" |
22 | | |
23 | | #include <algorithm> |
24 | | #include <cstdlib> |
25 | | #include <limits> |
26 | | |
27 | | // Specification at |
28 | | // https://www.nrcan.gc.ca/sites/www.nrcan.gc.ca/files/earthsciences/pdf/gpshgrid_e.pdf |
29 | | |
30 | | const static BYNEllipsoids EllipsoidTable[] = { |
31 | | {"GRS80", 6378137.0, 298.257222101}, |
32 | | {"WGS84", 6378137.0, 298.257223564}, |
33 | | {"ALT1", 6378136.3, 298.256415099}, |
34 | | {"GRS67", 6378160.0, 298.247167427}, |
35 | | {"ELLIP1", 6378136.46, 298.256415099}, |
36 | | {"ALT2", 6378136.3, 298.257}, |
37 | | {"ELLIP2", 6378136.0, 298.257}, |
38 | | {"CLARKE 1866", 6378206.4, 294.9786982}}; |
39 | | |
40 | | /************************************************************************/ |
41 | | /* BYNRasterBand() */ |
42 | | /************************************************************************/ |
43 | | |
44 | | BYNRasterBand::BYNRasterBand(GDALDataset *poDSIn, int nBandIn, |
45 | | VSILFILE *fpRawIn, vsi_l_offset nImgOffsetIn, |
46 | | int nPixelOffsetIn, int nLineOffsetIn, |
47 | | GDALDataType eDataTypeIn, int bNativeOrderIn) |
48 | 647 | : RawRasterBand(poDSIn, nBandIn, fpRawIn, nImgOffsetIn, nPixelOffsetIn, |
49 | 647 | nLineOffsetIn, eDataTypeIn, bNativeOrderIn, |
50 | 647 | RawRasterBand::OwnFP::NO) |
51 | 647 | { |
52 | 647 | } |
53 | | |
54 | | /************************************************************************/ |
55 | | /* ~BYNRasterBand() */ |
56 | | /************************************************************************/ |
57 | | |
58 | | BYNRasterBand::~BYNRasterBand() |
59 | 647 | { |
60 | 647 | } |
61 | | |
62 | | /************************************************************************/ |
63 | | /* GetNoDataValue() */ |
64 | | /************************************************************************/ |
65 | | |
66 | | double BYNRasterBand::GetNoDataValue(int *pbSuccess) |
67 | 182k | { |
68 | 182k | if (pbSuccess) |
69 | 182k | *pbSuccess = TRUE; |
70 | 182k | int bSuccess = FALSE; |
71 | 182k | double dfNoData = GDALPamRasterBand::GetNoDataValue(&bSuccess); |
72 | 182k | if (bSuccess) |
73 | 0 | { |
74 | 0 | return dfNoData; |
75 | 0 | } |
76 | 182k | const double dfFactor = |
77 | 182k | reinterpret_cast<BYNDataset *>(poDS)->hHeader.dfFactor; |
78 | 182k | return eDataType == GDT_Int16 ? 32767.0 : 9999.0 * dfFactor; |
79 | 182k | } |
80 | | |
81 | | /************************************************************************/ |
82 | | /* GetScale() */ |
83 | | /************************************************************************/ |
84 | | |
85 | | double BYNRasterBand::GetScale(int *pbSuccess) |
86 | 16.2k | { |
87 | 16.2k | if (pbSuccess != nullptr) |
88 | 72 | *pbSuccess = TRUE; |
89 | 16.2k | const double dfFactor = |
90 | 16.2k | reinterpret_cast<BYNDataset *>(poDS)->hHeader.dfFactor; |
91 | 16.2k | return (dfFactor != 0.0) ? 1.0 / dfFactor : 0.0; |
92 | 16.2k | } |
93 | | |
94 | | /************************************************************************/ |
95 | | /* ==================================================================== */ |
96 | | /* BYNDataset */ |
97 | | /* ==================================================================== */ |
98 | | /************************************************************************/ |
99 | | |
100 | | BYNDataset::BYNDataset() |
101 | 653 | : fpImage(nullptr), hHeader{0, 0, 0, 0, 0, 0, 0, 0, 0.0, 0, 0, 0, |
102 | 653 | 0, 0, 0, 0, 0, 0.0, 0.0, 0, 0, 0.0, 0} |
103 | 653 | { |
104 | 653 | m_oSRS.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER); |
105 | 653 | adfGeoTransform[0] = 0.0; |
106 | 653 | adfGeoTransform[1] = 1.0; |
107 | 653 | adfGeoTransform[2] = 0.0; |
108 | 653 | adfGeoTransform[3] = 0.0; |
109 | 653 | adfGeoTransform[4] = 0.0; |
110 | 653 | adfGeoTransform[5] = 1.0; |
111 | 653 | } |
112 | | |
113 | | /************************************************************************/ |
114 | | /* ~BYNDataset() */ |
115 | | /************************************************************************/ |
116 | | |
117 | | BYNDataset::~BYNDataset() |
118 | | |
119 | 653 | { |
120 | 653 | BYNDataset::Close(); |
121 | 653 | } |
122 | | |
123 | | /************************************************************************/ |
124 | | /* Close() */ |
125 | | /************************************************************************/ |
126 | | |
127 | | CPLErr BYNDataset::Close() |
128 | 1.30k | { |
129 | 1.30k | CPLErr eErr = CE_None; |
130 | 1.30k | if (nOpenFlags != OPEN_FLAGS_CLOSED) |
131 | 653 | { |
132 | 653 | if (BYNDataset::FlushCache(true) != CE_None) |
133 | 13 | eErr = CE_Failure; |
134 | | |
135 | 653 | if (fpImage != nullptr) |
136 | 653 | { |
137 | 653 | if (VSIFCloseL(fpImage) != 0) |
138 | 0 | { |
139 | 0 | eErr = CE_Failure; |
140 | 0 | CPLError(CE_Failure, CPLE_FileIO, "I/O error"); |
141 | 0 | } |
142 | 653 | } |
143 | | |
144 | 653 | if (GDALPamDataset::Close() != CE_None) |
145 | 0 | eErr = CE_Failure; |
146 | 653 | } |
147 | 1.30k | return eErr; |
148 | 1.30k | } |
149 | | |
150 | | /************************************************************************/ |
151 | | /* Identify() */ |
152 | | /************************************************************************/ |
153 | | |
154 | | int BYNDataset::Identify(GDALOpenInfo *poOpenInfo) |
155 | | |
156 | 40.0k | { |
157 | 40.0k | if (poOpenInfo->nHeaderBytes < BYN_HDR_SZ) |
158 | 26.0k | return FALSE; |
159 | | |
160 | | /* -------------------------------------------------------------------- */ |
161 | | /* Check file extension (.byn/.err) */ |
162 | | /* -------------------------------------------------------------------- */ |
163 | | #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION |
164 | | const char *pszFileExtension = poOpenInfo->osExtension.c_str(); |
165 | | |
166 | | if (!EQUAL(pszFileExtension, "byn") && !EQUAL(pszFileExtension, "err")) |
167 | | { |
168 | | return FALSE; |
169 | | } |
170 | | #endif |
171 | | |
172 | | /* -------------------------------------------------------------------- */ |
173 | | /* Check some value's ranges on header */ |
174 | | /* -------------------------------------------------------------------- */ |
175 | | |
176 | 14.0k | BYNHeader hHeader = {0, 0, 0, 0, 0, 0, 0, 0, 0.0, 0, 0, 0, |
177 | 14.0k | 0, 0, 0, 0, 0, 0.0, 0.0, 0, 0, 0.0, 0}; |
178 | | |
179 | 14.0k | buffer2header(poOpenInfo->pabyHeader, &hHeader); |
180 | | |
181 | 14.0k | if (hHeader.nGlobal < 0 || hHeader.nGlobal > 1 || hHeader.nType < 0 || |
182 | 14.0k | hHeader.nType > 9 || (hHeader.nSizeOf != 2 && hHeader.nSizeOf != 4) || |
183 | 14.0k | hHeader.nVDatum < 0 || hHeader.nVDatum > 3 || hHeader.nDescrip < 0 || |
184 | 14.0k | hHeader.nDescrip > 3 || hHeader.nSubType < 0 || hHeader.nSubType > 9 || |
185 | 14.0k | hHeader.nDatum < 0 || hHeader.nDatum > 1 || hHeader.nEllipsoid < 0 || |
186 | 14.0k | hHeader.nEllipsoid > 7 || hHeader.nByteOrder < 0 || |
187 | 14.0k | hHeader.nByteOrder > 1 || hHeader.nScale < 0 || hHeader.nScale > 1) |
188 | 12.6k | return FALSE; |
189 | | |
190 | | #if 0 |
191 | | // We have disabled those checks as invalid values are often found in some |
192 | | // datasets, such as http://s3.microsurvey.com/os/fieldgenius/geoids/Lithuania.zip |
193 | | // We don't use those fields, so we may just ignore them. |
194 | | if((hHeader.nTideSys < 0 || hHeader.nTideSys > 2 || |
195 | | hHeader.nPtType < 0 || hHeader.nPtType > 1 )) |
196 | | { |
197 | | // Some datasets use 0xCC as a marker for invalidity for |
198 | | // records starting from Geopotential Wo |
199 | | for( int i = 52; i < 78; i++ ) |
200 | | { |
201 | | if( poOpenInfo->pabyHeader[i] != 0xCC ) |
202 | | return FALSE; |
203 | | } |
204 | | } |
205 | | #endif |
206 | | |
207 | 1.32k | if (hHeader.nScale == 0) |
208 | 1.32k | { |
209 | 1.32k | if ((std::abs(static_cast<GIntBig>(hHeader.nSouth) - |
210 | 1.32k | (hHeader.nDLat / 2)) > BYN_MAX_LAT) || |
211 | 1.32k | (std::abs(static_cast<GIntBig>(hHeader.nNorth) + |
212 | 1.31k | (hHeader.nDLat / 2)) > BYN_MAX_LAT) || |
213 | 1.32k | (std::abs(static_cast<GIntBig>(hHeader.nWest) - |
214 | 1.31k | (hHeader.nDLon / 2)) > BYN_MAX_LON) || |
215 | 1.32k | (std::abs(static_cast<GIntBig>(hHeader.nEast) + |
216 | 1.30k | (hHeader.nDLon / 2)) > BYN_MAX_LON)) |
217 | 21 | return FALSE; |
218 | 1.32k | } |
219 | 1 | else |
220 | 1 | { |
221 | 1 | if ((std::abs(static_cast<GIntBig>(hHeader.nSouth) - |
222 | 1 | (hHeader.nDLat / 2)) > BYN_MAX_LAT_SCL) || |
223 | 1 | (std::abs(static_cast<GIntBig>(hHeader.nNorth) + |
224 | 0 | (hHeader.nDLat / 2)) > BYN_MAX_LAT_SCL) || |
225 | 1 | (std::abs(static_cast<GIntBig>(hHeader.nWest) - |
226 | 0 | (hHeader.nDLon / 2)) > BYN_MAX_LON_SCL) || |
227 | 1 | (std::abs(static_cast<GIntBig>(hHeader.nEast) + |
228 | 0 | (hHeader.nDLon / 2)) > BYN_MAX_LON_SCL)) |
229 | 1 | return FALSE; |
230 | 1 | } |
231 | | |
232 | 1.30k | return TRUE; |
233 | 1.32k | } |
234 | | |
235 | | /************************************************************************/ |
236 | | /* Open() */ |
237 | | /************************************************************************/ |
238 | | |
239 | | GDALDataset *BYNDataset::Open(GDALOpenInfo *poOpenInfo) |
240 | | |
241 | 653 | { |
242 | 653 | if (!Identify(poOpenInfo) || poOpenInfo->fpL == nullptr || |
243 | 653 | poOpenInfo->eAccess == GA_Update) |
244 | 0 | return nullptr; |
245 | | |
246 | | /* -------------------------------------------------------------------- */ |
247 | | /* Create a corresponding GDALDataset. */ |
248 | | /* -------------------------------------------------------------------- */ |
249 | | |
250 | 653 | auto poDS = std::make_unique<BYNDataset>(); |
251 | | |
252 | 653 | poDS->eAccess = poOpenInfo->eAccess; |
253 | 653 | std::swap(poDS->fpImage, poOpenInfo->fpL); |
254 | | |
255 | | /* -------------------------------------------------------------------- */ |
256 | | /* Read the header. */ |
257 | | /* -------------------------------------------------------------------- */ |
258 | | |
259 | 653 | buffer2header(poOpenInfo->pabyHeader, &poDS->hHeader); |
260 | | |
261 | | /********************************/ |
262 | | /* Scale boundaries and spacing */ |
263 | | /********************************/ |
264 | | |
265 | 653 | double dfSouth = poDS->hHeader.nSouth; |
266 | 653 | double dfNorth = poDS->hHeader.nNorth; |
267 | 653 | double dfWest = poDS->hHeader.nWest; |
268 | 653 | double dfEast = poDS->hHeader.nEast; |
269 | 653 | double dfDLat = poDS->hHeader.nDLat; |
270 | 653 | double dfDLon = poDS->hHeader.nDLon; |
271 | | |
272 | 653 | if (poDS->hHeader.nScale == 1) |
273 | 0 | { |
274 | 0 | dfSouth *= BYN_SCALE; |
275 | 0 | dfNorth *= BYN_SCALE; |
276 | 0 | dfWest *= BYN_SCALE; |
277 | 0 | dfEast *= BYN_SCALE; |
278 | 0 | dfDLat *= BYN_SCALE; |
279 | 0 | dfDLon *= BYN_SCALE; |
280 | 0 | } |
281 | | |
282 | | /******************************/ |
283 | | /* Calculate rows and columns */ |
284 | | /******************************/ |
285 | | |
286 | 653 | double dfXSize = -1; |
287 | 653 | double dfYSize = -1; |
288 | | |
289 | 653 | poDS->nRasterXSize = -1; |
290 | 653 | poDS->nRasterYSize = -1; |
291 | | |
292 | 653 | if (dfDLat != 0.0 && dfDLon != 0.0) |
293 | 650 | { |
294 | 650 | dfXSize = ((dfEast - dfWest + 1.0) / dfDLon) + 1.0; |
295 | 650 | dfYSize = ((dfNorth - dfSouth + 1.0) / dfDLat) + 1.0; |
296 | 650 | } |
297 | | |
298 | 653 | if (dfXSize > 0.0 && dfXSize < std::numeric_limits<double>::max() && |
299 | 653 | dfYSize > 0.0 && dfYSize < std::numeric_limits<double>::max()) |
300 | 647 | { |
301 | 647 | poDS->nRasterXSize = static_cast<GInt32>(dfXSize); |
302 | 647 | poDS->nRasterYSize = static_cast<GInt32>(dfYSize); |
303 | 647 | } |
304 | | |
305 | 653 | if (!GDALCheckDatasetDimensions(poDS->nRasterXSize, poDS->nRasterYSize)) |
306 | 6 | { |
307 | 6 | return nullptr; |
308 | 6 | } |
309 | | |
310 | | /*****************************/ |
311 | | /* Build GeoTransform matrix */ |
312 | | /*****************************/ |
313 | | |
314 | 647 | poDS->adfGeoTransform[0] = (dfWest - (dfDLon / 2.0)) / 3600.0; |
315 | 647 | poDS->adfGeoTransform[1] = dfDLon / 3600.0; |
316 | 647 | poDS->adfGeoTransform[2] = 0.0; |
317 | 647 | poDS->adfGeoTransform[3] = (dfNorth + (dfDLat / 2.0)) / 3600.0; |
318 | 647 | poDS->adfGeoTransform[4] = 0.0; |
319 | 647 | poDS->adfGeoTransform[5] = -1 * dfDLat / 3600.0; |
320 | | |
321 | | /*********************/ |
322 | | /* Set data type */ |
323 | | /*********************/ |
324 | | |
325 | 647 | GDALDataType eDT = GDT_Unknown; |
326 | | |
327 | 647 | if (poDS->hHeader.nSizeOf == 2) |
328 | 197 | eDT = GDT_Int16; |
329 | 450 | else if (poDS->hHeader.nSizeOf == 4) |
330 | 450 | eDT = GDT_Int32; |
331 | 0 | else |
332 | 0 | { |
333 | 0 | return nullptr; |
334 | 0 | } |
335 | | |
336 | | /* -------------------------------------------------------------------- */ |
337 | | /* Create band information object. */ |
338 | | /* -------------------------------------------------------------------- */ |
339 | | |
340 | 647 | const int nDTSize = GDALGetDataTypeSizeBytes(eDT); |
341 | | |
342 | 647 | int bIsLSB = poDS->hHeader.nByteOrder == 1 ? 1 : 0; |
343 | | |
344 | 647 | auto poBand = std::make_unique<BYNRasterBand>( |
345 | 647 | poDS.get(), 1, poDS->fpImage, BYN_HDR_SZ, nDTSize, |
346 | 647 | poDS->nRasterXSize * nDTSize, eDT, CPL_IS_LSB == bIsLSB); |
347 | 647 | if (!poBand->IsValid()) |
348 | 0 | return nullptr; |
349 | 647 | poDS->SetBand(1, std::move(poBand)); |
350 | | |
351 | | /* -------------------------------------------------------------------- */ |
352 | | /* Initialize any PAM information. */ |
353 | | /* -------------------------------------------------------------------- */ |
354 | | |
355 | 647 | poDS->SetDescription(poOpenInfo->pszFilename); |
356 | 647 | poDS->TryLoadXML(); |
357 | | |
358 | | /* -------------------------------------------------------------------- */ |
359 | | /* Check for overviews. */ |
360 | | /* -------------------------------------------------------------------- */ |
361 | | |
362 | 647 | poDS->oOvManager.Initialize(poDS.get(), poOpenInfo->pszFilename); |
363 | | |
364 | 647 | return poDS.release(); |
365 | 647 | } |
366 | | |
367 | | /************************************************************************/ |
368 | | /* GetGeoTransform() */ |
369 | | /************************************************************************/ |
370 | | |
371 | | CPLErr BYNDataset::GetGeoTransform(double *padfTransform) |
372 | | |
373 | 783 | { |
374 | 783 | memcpy(padfTransform, adfGeoTransform, sizeof(double) * 6); |
375 | 783 | return CE_None; |
376 | 783 | } |
377 | | |
378 | | /************************************************************************/ |
379 | | /* GetSpatialRef() */ |
380 | | /************************************************************************/ |
381 | | |
382 | | const OGRSpatialReference *BYNDataset::GetSpatialRef() const |
383 | | |
384 | 690 | { |
385 | 690 | if (!m_oSRS.IsEmpty()) |
386 | 74 | return &m_oSRS; |
387 | | |
388 | | /* Try to use a prefefined EPSG compound CS */ |
389 | | |
390 | 616 | if (hHeader.nDatum == 1 && hHeader.nVDatum == 2) |
391 | 18 | { |
392 | 18 | m_oSRS.importFromEPSG(BYN_DATUM_1_VDATUM_2); |
393 | 18 | return &m_oSRS; |
394 | 18 | } |
395 | | |
396 | | /* Build the GEOGCS based on Datum ( or Ellipsoid )*/ |
397 | | |
398 | 598 | bool bNoGeogCS = false; |
399 | | |
400 | 598 | if (hHeader.nDatum == 0) |
401 | 267 | m_oSRS.importFromEPSG(BYN_DATUM_0); |
402 | 331 | else if (hHeader.nDatum == 1) |
403 | 331 | m_oSRS.importFromEPSG(BYN_DATUM_1); |
404 | 0 | else |
405 | 0 | { |
406 | | /* Build GEOGCS based on Ellipsoid (Table 3) */ |
407 | |
|
408 | 0 | if (hHeader.nEllipsoid > -1 && |
409 | 0 | hHeader.nEllipsoid < |
410 | 0 | static_cast<GInt16>(CPL_ARRAYSIZE(EllipsoidTable))) |
411 | 0 | m_oSRS.SetGeogCS( |
412 | 0 | CPLSPrintf("BYN Ellipsoid(%d)", hHeader.nEllipsoid), |
413 | 0 | "Unspecified", EllipsoidTable[hHeader.nEllipsoid].pszName, |
414 | 0 | EllipsoidTable[hHeader.nEllipsoid].dfSemiMajor, |
415 | 0 | EllipsoidTable[hHeader.nEllipsoid].dfInvFlattening); |
416 | 0 | else |
417 | 0 | bNoGeogCS = true; |
418 | 0 | } |
419 | | |
420 | | /* Build the VERT_CS based on VDatum */ |
421 | | |
422 | 598 | OGRSpatialReference oSRSComp; |
423 | 598 | OGRSpatialReference oSRSVert; |
424 | | |
425 | 598 | int nVertCS = 0; |
426 | | |
427 | 598 | if (hHeader.nVDatum == 1) |
428 | 436 | nVertCS = BYN_VDATUM_1; |
429 | 162 | else if (hHeader.nVDatum == 2) |
430 | 152 | nVertCS = BYN_VDATUM_2; |
431 | 10 | else if (hHeader.nVDatum == 3) |
432 | 5 | nVertCS = BYN_VDATUM_3; |
433 | 5 | else |
434 | 5 | { |
435 | | /* Return GEOGCS ( .err files ) */ |
436 | | |
437 | 5 | if (bNoGeogCS) |
438 | 0 | return nullptr; |
439 | | |
440 | 5 | return &m_oSRS; |
441 | 5 | } |
442 | | |
443 | 593 | oSRSVert.importFromEPSG(nVertCS); |
444 | | |
445 | | /* Create CPMPD_CS with GEOGCS and VERT_CS */ |
446 | | |
447 | 593 | if (oSRSComp.SetCompoundCS(CPLSPrintf("BYN Datum(%d) & VDatum(%d)", |
448 | 593 | hHeader.nDatum, hHeader.nDatum), |
449 | 593 | &m_oSRS, &oSRSVert) == CE_None) |
450 | 593 | { |
451 | | /* Return COMPD_CS with GEOGCS and VERT_CS */ |
452 | | |
453 | 593 | m_oSRS = std::move(oSRSComp); |
454 | 593 | m_oSRS.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER); |
455 | 593 | return &m_oSRS; |
456 | 593 | } |
457 | | |
458 | 0 | return nullptr; |
459 | 593 | } |
460 | | |
461 | | /*----------------------------------------------------------------------*/ |
462 | | /* buffer2header() */ |
463 | | /*----------------------------------------------------------------------*/ |
464 | | |
465 | | void BYNDataset::buffer2header(const GByte *pabyBuf, BYNHeader *pohHeader) |
466 | | |
467 | 14.6k | { |
468 | 14.6k | memcpy(&pohHeader->nSouth, pabyBuf, 4); |
469 | 14.6k | memcpy(&pohHeader->nNorth, pabyBuf + 4, 4); |
470 | 14.6k | memcpy(&pohHeader->nWest, pabyBuf + 8, 4); |
471 | 14.6k | memcpy(&pohHeader->nEast, pabyBuf + 12, 4); |
472 | 14.6k | memcpy(&pohHeader->nDLat, pabyBuf + 16, 2); |
473 | 14.6k | memcpy(&pohHeader->nDLon, pabyBuf + 18, 2); |
474 | 14.6k | memcpy(&pohHeader->nGlobal, pabyBuf + 20, 2); |
475 | 14.6k | memcpy(&pohHeader->nType, pabyBuf + 22, 2); |
476 | 14.6k | memcpy(&pohHeader->dfFactor, pabyBuf + 24, 8); |
477 | 14.6k | memcpy(&pohHeader->nSizeOf, pabyBuf + 32, 2); |
478 | 14.6k | memcpy(&pohHeader->nVDatum, pabyBuf + 34, 2); |
479 | 14.6k | memcpy(&pohHeader->nDescrip, pabyBuf + 40, 2); |
480 | 14.6k | memcpy(&pohHeader->nSubType, pabyBuf + 42, 2); |
481 | 14.6k | memcpy(&pohHeader->nDatum, pabyBuf + 44, 2); |
482 | 14.6k | memcpy(&pohHeader->nEllipsoid, pabyBuf + 46, 2); |
483 | 14.6k | memcpy(&pohHeader->nByteOrder, pabyBuf + 48, 2); |
484 | 14.6k | memcpy(&pohHeader->nScale, pabyBuf + 50, 2); |
485 | 14.6k | memcpy(&pohHeader->dfWo, pabyBuf + 52, 8); |
486 | 14.6k | memcpy(&pohHeader->dfGM, pabyBuf + 60, 8); |
487 | 14.6k | memcpy(&pohHeader->nTideSys, pabyBuf + 68, 2); |
488 | 14.6k | memcpy(&pohHeader->nRealiz, pabyBuf + 70, 2); |
489 | 14.6k | memcpy(&pohHeader->dEpoch, pabyBuf + 72, 4); |
490 | 14.6k | memcpy(&pohHeader->nPtType, pabyBuf + 76, 2); |
491 | | |
492 | | #if defined(CPL_MSB) |
493 | | CPL_LSBPTR32(&pohHeader->nSouth); |
494 | | CPL_LSBPTR32(&pohHeader->nNorth); |
495 | | CPL_LSBPTR32(&pohHeader->nWest); |
496 | | CPL_LSBPTR32(&pohHeader->nEast); |
497 | | CPL_LSBPTR16(&pohHeader->nDLat); |
498 | | CPL_LSBPTR16(&pohHeader->nDLon); |
499 | | CPL_LSBPTR16(&pohHeader->nGlobal); |
500 | | CPL_LSBPTR16(&pohHeader->nType); |
501 | | CPL_LSBPTR64(&pohHeader->dfFactor); |
502 | | CPL_LSBPTR16(&pohHeader->nSizeOf); |
503 | | CPL_LSBPTR16(&pohHeader->nVDatum); |
504 | | CPL_LSBPTR16(&pohHeader->nDescrip); |
505 | | CPL_LSBPTR16(&pohHeader->nSubType); |
506 | | CPL_LSBPTR16(&pohHeader->nDatum); |
507 | | CPL_LSBPTR16(&pohHeader->nEllipsoid); |
508 | | CPL_LSBPTR16(&pohHeader->nByteOrder); |
509 | | CPL_LSBPTR16(&pohHeader->nScale); |
510 | | CPL_LSBPTR64(&pohHeader->dfWo); |
511 | | CPL_LSBPTR64(&pohHeader->dfGM); |
512 | | CPL_LSBPTR16(&pohHeader->nTideSys); |
513 | | CPL_LSBPTR16(&pohHeader->nRealiz); |
514 | | CPL_LSBPTR32(&pohHeader->dEpoch); |
515 | | CPL_LSBPTR16(&pohHeader->nPtType); |
516 | | #endif |
517 | | |
518 | | #if DEBUG |
519 | | CPLDebug("BYN", "South = %d", pohHeader->nSouth); |
520 | | CPLDebug("BYN", "North = %d", pohHeader->nNorth); |
521 | | CPLDebug("BYN", "West = %d", pohHeader->nWest); |
522 | | CPLDebug("BYN", "East = %d", pohHeader->nEast); |
523 | | CPLDebug("BYN", "DLat = %d", pohHeader->nDLat); |
524 | | CPLDebug("BYN", "DLon = %d", pohHeader->nDLon); |
525 | | CPLDebug("BYN", "DGlobal = %d", pohHeader->nGlobal); |
526 | | CPLDebug("BYN", "DType = %d", pohHeader->nType); |
527 | | CPLDebug("BYN", "Factor = %f", pohHeader->dfFactor); |
528 | | CPLDebug("BYN", "SizeOf = %d", pohHeader->nSizeOf); |
529 | | CPLDebug("BYN", "VDatum = %d", pohHeader->nVDatum); |
530 | | CPLDebug("BYN", "Data = %d", pohHeader->nDescrip); |
531 | | CPLDebug("BYN", "SubType = %d", pohHeader->nSubType); |
532 | | CPLDebug("BYN", "Datum = %d", pohHeader->nDatum); |
533 | | CPLDebug("BYN", "Ellipsoid = %d", pohHeader->nEllipsoid); |
534 | | CPLDebug("BYN", "ByteOrder = %d", pohHeader->nByteOrder); |
535 | | CPLDebug("BYN", "Scale = %d", pohHeader->nScale); |
536 | | CPLDebug("BYN", "Wo = %f", pohHeader->dfWo); |
537 | | CPLDebug("BYN", "GM = %f", pohHeader->dfGM); |
538 | | CPLDebug("BYN", "TideSystem = %d", pohHeader->nTideSys); |
539 | | CPLDebug("BYN", "RefRealzation = %d", pohHeader->nRealiz); |
540 | | CPLDebug("BYN", "Epoch = %f", pohHeader->dEpoch); |
541 | | CPLDebug("BYN", "PtType = %d", pohHeader->nPtType); |
542 | | #endif |
543 | 14.6k | } |
544 | | |
545 | | /************************************************************************/ |
546 | | /* GDALRegister_BYN() */ |
547 | | /************************************************************************/ |
548 | | |
549 | | void GDALRegister_BYN() |
550 | | |
551 | 2 | { |
552 | 2 | if (GDALGetDriverByName("BYN") != nullptr) |
553 | 0 | return; |
554 | | |
555 | 2 | GDALDriver *poDriver = new GDALDriver(); |
556 | | |
557 | 2 | poDriver->SetDescription("BYN"); |
558 | 2 | poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES"); |
559 | 2 | poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, |
560 | 2 | "Natural Resources Canada's Geoid"); |
561 | 2 | poDriver->SetMetadataItem(GDAL_DMD_EXTENSIONS, "byn err"); |
562 | 2 | poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES"); |
563 | 2 | poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drivers/raster/byn.html"); |
564 | | |
565 | 2 | poDriver->pfnOpen = BYNDataset::Open; |
566 | 2 | poDriver->pfnIdentify = BYNDataset::Identify; |
567 | | |
568 | 2 | GetGDALDriverManager()->RegisterDriver(poDriver); |
569 | 2 | } |