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