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