Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: MSG Native Reader
4 : * Purpose: Base class for reading in the headers of MSG native images
5 : * Author: Frans van den Bergh, fvdbergh@csir.co.za
6 : *
7 : ******************************************************************************
8 : * Copyright (c) 2005, Frans van den Bergh <fvdbergh@csir.co.za>
9 : *
10 : * SPDX-License-Identifier: MIT
11 : ****************************************************************************/
12 :
13 : #include "cpl_port.h"
14 : #include "cpl_error.h"
15 :
16 : #include "msg_reader_core.h"
17 : #include "msg_basic_types.h"
18 : #include <stdio.h>
19 : #include <string.h>
20 : #include <math.h>
21 :
22 : #ifdef DEBUG
23 : #ifdef GDAL_SUPPORT
24 : #undef DEBUG
25 : #endif
26 : #endif
27 :
28 : #ifdef GDAL_SUPPORT
29 : #include "cpl_vsi.h"
30 :
31 : #else
32 : #define VSIFSeek(fp, pos, ref) CPL_IGNORE_RET_VAL(fseek(fp, pos, ref))
33 : #define VSIFRead(p, bs, nb, fp) CPL_IGNORE_RET_VAL(fread(p, bs, nb, fp))
34 : #endif
35 :
36 : namespace msg_native_format
37 : {
38 :
39 : const Blackbody_lut_type Msg_reader_core::Blackbody_LUT[MSG_NUM_CHANNELS + 1] =
40 : {
41 : {0, 0, 0}, // dummy channel
42 : {0, 0, 0}, // N/A
43 : {0, 0, 0}, // N/A
44 : {0, 0, 0}, // N/A
45 : {2569.094, 0.9959, 3.471},
46 : {1598.566, 0.9963, 2.219},
47 : {1362.142, 0.9991, 0.485},
48 : {1149.083, 0.9996, 0.181},
49 : {1034.345, 0.9999, 0.060},
50 : {930.659, 0.9983, 0.627},
51 : {839.661, 0.9988, 0.397},
52 : {752.381, 0.9981, 0.576},
53 : {0, 0, 0} // N/A
54 : };
55 :
56 0 : static void PhDataInit(PH_DATA *data)
57 : {
58 0 : data->name[0] = '\0';
59 0 : data->value[0] = '\0';
60 0 : }
61 :
62 0 : static void SecondaryProdHeaderInit(SECONDARY_PROD_HEADER *header)
63 : {
64 0 : PhDataInit(&header->abid);
65 0 : PhDataInit(&header->smod);
66 0 : PhDataInit(&header->apxs);
67 0 : PhDataInit(&header->avpa);
68 0 : PhDataInit(&header->lscd);
69 0 : PhDataInit(&header->lmap);
70 0 : PhDataInit(&header->qdlc);
71 0 : PhDataInit(&header->qdlp);
72 0 : PhDataInit(&header->qqai);
73 0 : PhDataInit(&header->selectedBandIds);
74 0 : PhDataInit(&header->southLineSelectedRectangle);
75 0 : PhDataInit(&header->northLineSelectedRectangle);
76 0 : PhDataInit(&header->eastColumnSelectedRectangle);
77 0 : PhDataInit(&header->westColumnSelectedRectangle);
78 0 : }
79 :
80 0 : Msg_reader_core::Msg_reader_core(const char *fname)
81 : : _lines(0), _columns(0), _line_start(0), _col_start(0),
82 : _col_dir_step(0.0f), _line_dir_step(0.0f), _hrv_col_dir_step(0.0f),
83 : _hrv_line_dir_step(0.0f), _f_data_offset(0), _f_data_size(0),
84 : _f_header_offset(0), _f_header_size(0), _f_trailer_offset(0),
85 : _f_trailer_size(0), _visir_bytes_per_line(0), _visir_packet_size(0),
86 : _hrv_bytes_per_line(0), _hrv_packet_size(0), _interline_spacing(0),
87 0 : _year(0), _month(0), _day(0), _hour(0), _minute(0), _open_success(false)
88 : {
89 0 : memset(&_main_header, 0, sizeof(_main_header));
90 0 : memset(&_sec_header, 0, sizeof(_sec_header));
91 0 : SecondaryProdHeaderInit(&_sec_header);
92 0 : for (size_t i = 0; i < MSG_NUM_CHANNELS; ++i)
93 : {
94 0 : _calibration[i].cal_slope = 0.0;
95 0 : _calibration[i].cal_offset = 0.0;
96 : }
97 0 : memset(&_img_desc_record, 0, sizeof(_img_desc_record));
98 :
99 0 : VSILFILE *fin = VSIFOpenL(fname, "rb");
100 0 : if (!fin)
101 : {
102 0 : CPLError(CE_Failure, CPLE_OpenFailed, "Could not open file %s", fname);
103 0 : return;
104 : }
105 0 : read_metadata_block(fin);
106 0 : VSIFCloseL(fin);
107 : }
108 :
109 0 : Msg_reader_core::Msg_reader_core(VSILFILE *fp)
110 : : _lines(0), _columns(0), _line_start(0), _col_start(0),
111 : _col_dir_step(0.0f), _line_dir_step(0.0f), _hrv_col_dir_step(0.0f),
112 : _hrv_line_dir_step(0.0f), _f_data_offset(0), _f_data_size(0),
113 : _f_header_offset(0), _f_header_size(0), _f_trailer_offset(0),
114 : _f_trailer_size(0), _visir_bytes_per_line(0), _visir_packet_size(0),
115 : _hrv_bytes_per_line(0), _hrv_packet_size(0), _interline_spacing(0),
116 0 : _year(0), _month(0), _day(0), _hour(0), _minute(0), _open_success(false)
117 : {
118 0 : memset(&_main_header, 0, sizeof(_main_header));
119 0 : memset(&_sec_header, 0, sizeof(_sec_header));
120 :
121 0 : SecondaryProdHeaderInit(&_sec_header);
122 0 : for (size_t i = 0; i < MSG_NUM_CHANNELS; ++i)
123 : {
124 0 : _calibration[i].cal_slope = 0.0;
125 0 : _calibration[i].cal_offset = 0.0;
126 : }
127 0 : memset(&_img_desc_record, 0, sizeof(_img_desc_record));
128 :
129 0 : read_metadata_block(fp);
130 0 : }
131 :
132 : Msg_reader_core::~Msg_reader_core() = default;
133 :
134 0 : void Msg_reader_core::read_metadata_block(VSILFILE *fin)
135 : {
136 0 : _open_success = true;
137 :
138 : unsigned int i;
139 :
140 0 : CPL_IGNORE_RET_VAL(VSIFReadL(&_main_header, sizeof(_main_header), 1, fin));
141 0 : CPL_IGNORE_RET_VAL(VSIFReadL(&_sec_header, sizeof(_sec_header), 1, fin));
142 :
143 : PH_DATA_ID *hdi;
144 :
145 : #ifdef DEBUG
146 : // print out all the fields in the header
147 : PH_DATA *hd = reinterpret_cast<PH_DATA *>(&_main_header);
148 : for (i = 0; i < 6; i++)
149 : {
150 : to_string(*hd);
151 : printf("[%02u] %s %s", i, hd->name, hd->value); /*ok*/
152 : hd++;
153 : }
154 :
155 : hdi = (PH_DATA_ID *)&_main_header.dataSetIdentification;
156 : for (i = 0; i < 5; i++)
157 : {
158 : printf("%s %s %s", hdi->name, hdi->size, hdi->address); /*ok*/
159 : hdi++;
160 : }
161 :
162 : hd = (PH_DATA *)(&_main_header.totalFileSize);
163 : for (i = 0; i < 19; i++)
164 : {
165 : to_string(*hd);
166 : printf("[%02u] %s %s", i, hd->name, hd->value); /*ok*/
167 : hd++;
168 : }
169 : #endif // DEBUG
170 :
171 : // extract data & header positions
172 :
173 0 : for (i = 0; i < 5; i++)
174 : {
175 0 : hdi = (PH_DATA_ID *)&_main_header.dataSetIdentification[i];
176 0 : if (STARTS_WITH(hdi->name, "15Header"))
177 : {
178 0 : sscanf(hdi->size, "%u", &_f_header_size);
179 0 : sscanf(hdi->address, "%u", &_f_header_offset);
180 : }
181 0 : else if (STARTS_WITH(hdi->name, "15Trailer"))
182 : {
183 0 : sscanf(hdi->size, "%u", &_f_trailer_size);
184 0 : sscanf(hdi->address, "%u", &_f_trailer_offset);
185 : }
186 0 : else if (STARTS_WITH(hdi->name, "15Data"))
187 : {
188 0 : sscanf(hdi->size, "%u", &_f_data_size);
189 0 : sscanf(hdi->address, "%u", &_f_data_offset);
190 : }
191 : }
192 : #ifdef DEBUG
193 : printf("Data: %u %u\n", _f_data_offset, _f_data_size); /*ok*/
194 : printf("Header: %u %u\n", _f_header_offset, _f_header_size); /*ok*/
195 : printf("Trailer: %u %u\n", _f_trailer_offset, _f_trailer_size); /*ok*/
196 : #endif // DEBUG
197 :
198 : unsigned int lines;
199 0 : sscanf(_sec_header.northLineSelectedRectangle.value, "%u", &_lines);
200 0 : sscanf(_sec_header.southLineSelectedRectangle.value, "%u", &lines);
201 0 : _line_start = lines;
202 0 : if (lines > 0 &&
203 0 : _lines >=
204 0 : lines -
205 : 1) // if starting N of S edge, _lines counts what's there...
206 0 : _lines -= lines - 1;
207 :
208 : unsigned int cols;
209 0 : sscanf(_sec_header.westColumnSelectedRectangle.value, "%u", &_columns);
210 0 : sscanf(_sec_header.eastColumnSelectedRectangle.value, "%u", &cols);
211 0 : _col_start = cols;
212 0 : if (cols > 0 &&
213 0 : _columns >=
214 0 : cols - 1) // if starting W of the E edge, _cols counts what's there
215 0 : _columns -= cols - 1;
216 :
217 : #ifdef DEBUG
218 : printf("lines = %u, cols = %u\n", _lines, _columns); /*ok*/
219 : int records_per_line = 0;
220 : #endif // DEBUG
221 :
222 0 : for (i = 0; i < MSG_NUM_CHANNELS; i++)
223 : {
224 0 : if (_sec_header.selectedBandIds.value[i] == 'X')
225 : {
226 0 : _bands[i] = 1;
227 : #ifdef DEBUG
228 : records_per_line += (i == (MSG_NUM_CHANNELS - 1)) ? 3 : 1;
229 : #endif // DEBUG
230 : }
231 : else
232 : {
233 0 : _bands[i] = 0;
234 : }
235 : }
236 :
237 : #ifdef DEBUG
238 : printf("reading a total of %d records per line\n", records_per_line); /*ok*/
239 : #endif // DEBUG
240 :
241 : // extract time fields, assume that SNIT is the correct field:
242 0 : sscanf(_main_header.snit.value + 0, "%04u", &_year);
243 0 : sscanf(_main_header.snit.value + 4, "%02u", &_month);
244 0 : sscanf(_main_header.snit.value + 6, "%02u", &_day);
245 0 : sscanf(_main_header.snit.value + 8, "%02u", &_hour);
246 0 : sscanf(_main_header.snit.value + 10, "%02u", &_minute);
247 :
248 : // read radiometric block
249 : RADIOMETRIC_PROCESSING_RECORD rad;
250 0 : off_t offset = RADIOMETRICPROCESSING_RECORD_OFFSET + _f_header_offset +
251 0 : sizeof(GP_PK_HEADER) + sizeof(GP_PK_SH1) + 1;
252 0 : CPL_IGNORE_RET_VAL(
253 0 : VSIFSeekL(fin, static_cast<vsi_l_offset>(offset), SEEK_SET));
254 0 : CPL_IGNORE_RET_VAL(
255 0 : VSIFReadL(&rad, sizeof(RADIOMETRIC_PROCESSING_RECORD), 1, fin));
256 0 : to_native(rad);
257 0 : memcpy((void *)_calibration, (void *)&rad.level1_5ImageCalibration,
258 : sizeof(_calibration));
259 :
260 : #ifdef DEBUG
261 : for (i = 0; i < MSG_NUM_CHANNELS; i++)
262 : {
263 : if (_calibration[i].cal_slope < 0 || _calibration[i].cal_slope > 0.4)
264 : {
265 : printf(/*ok*/ "Warning: calibration slope (%f) out of nominal "
266 : "range. MSG "
267 : "reader probably broken\n",
268 : _calibration[i].cal_slope);
269 : }
270 : if (_calibration[i].cal_offset > 0 || _calibration[i].cal_offset < -20)
271 : {
272 : printf(/*ok*/ "Warning: calibration offset (%f) out of nominal "
273 : "range. MSG "
274 : "reader probably broken\n",
275 : _calibration[i].cal_offset);
276 : }
277 : }
278 : #endif
279 :
280 : // read image description block
281 0 : IMAGE_DESCRIPTION_RECORD &idr = _img_desc_record;
282 0 : offset = RADIOMETRICPROCESSING_RECORD_OFFSET -
283 0 : IMAGEDESCRIPTION_RECORD_LENGTH + _f_header_offset +
284 0 : sizeof(GP_PK_HEADER) + sizeof(GP_PK_SH1) + 1;
285 0 : CPL_IGNORE_RET_VAL(
286 0 : VSIFSeekL(fin, static_cast<vsi_l_offset>(offset), SEEK_SET));
287 0 : CPL_IGNORE_RET_VAL(
288 0 : VSIFReadL(&idr, sizeof(IMAGE_DESCRIPTION_RECORD), 1, fin));
289 0 : to_native(idr);
290 0 : CPLDebugOnly("MSGN", "idr.longitudeOfSSP = %g", idr.longitudeOfSSP);
291 0 : CPLDebugOnly("MSGN",
292 : "referencegrid_visir.numberOfLines = %d, "
293 : "referencegrid_visir.numberOfColumns = %d",
294 : idr.referencegrid_visir.numberOfLines,
295 : idr.referencegrid_visir.numberOfColumns);
296 0 : _line_dir_step = idr.referencegrid_visir.lineDirGridStep;
297 0 : _col_dir_step = idr.referencegrid_visir.columnDirGridStep;
298 0 : _hrv_line_dir_step = idr.referencegrid_hrv.lineDirGridStep;
299 0 : _hrv_col_dir_step = idr.referencegrid_hrv.columnDirGridStep;
300 :
301 0 : CPLDebugOnly("MSGN",
302 : "referencegrid_hrv.numberOfLines = %d, "
303 : "referencegrid_hrv.numberOfColumns = %d",
304 : idr.referencegrid_hrv.numberOfLines,
305 : idr.referencegrid_hrv.numberOfColumns);
306 :
307 0 : CPLDebugOnly("MSGN",
308 : "plannedCoverage_hrv.lowerSouthLinePlanned = %d, \n"
309 : "plannedCoverage_hrv.lowerNorthLinePlanned = %d, \n"
310 : "plannedCoverage_hrv.lowerEastColumnPlanned = %d, \n "
311 : "plannedCoverage_hrv.lowerWestColumnPlanned = %d",
312 : idr.plannedCoverage_hrv.lowerSouthLinePlanned,
313 : idr.plannedCoverage_hrv.lowerNorthLinePlanned,
314 : idr.plannedCoverage_hrv.lowerEastColumnPlanned,
315 : idr.plannedCoverage_hrv.lowerWestColumnPlanned);
316 :
317 0 : CPLDebugOnly("MSGN",
318 : "plannedCoverage_hrv.upperSouthLinePlanned = %d, \n"
319 : "plannedCoverage_hrv.upperNorthLinePlanned = %d, \n"
320 : "plannedCoverage_hrv.upperEastColumnPlanned = %d, \n "
321 : "plannedCoverage_hrv.upperWestColumnPlanned = %d",
322 : idr.plannedCoverage_hrv.upperSouthLinePlanned,
323 : idr.plannedCoverage_hrv.upperNorthLinePlanned,
324 : idr.plannedCoverage_hrv.upperEastColumnPlanned,
325 : idr.plannedCoverage_hrv.upperWestColumnPlanned);
326 :
327 : // Rather convoluted, but this code is required to compute the real data
328 : // block sizes It does this by reading in the first line of every band, to
329 : // get to the packet size field
330 : GP_PK_HEADER gp_header;
331 : GP_PK_SH1 sub_header;
332 : SUB_VISIRLINE visir_line;
333 :
334 0 : CPL_IGNORE_RET_VAL(
335 0 : VSIFSeekL(fin, static_cast<vsi_l_offset>(_f_data_offset), SEEK_SET));
336 :
337 0 : _hrv_packet_size = 0;
338 0 : _interline_spacing = 0;
339 0 : visir_line.channelId = 0;
340 :
341 : int scanned_bands[MSG_NUM_CHANNELS];
342 0 : int band_count = 0;
343 0 : for (i = 0; i < MSG_NUM_CHANNELS; i++)
344 : {
345 0 : scanned_bands[i] = _bands[i];
346 0 : band_count += _bands[i];
347 : }
348 :
349 0 : do
350 : {
351 0 : if (VSIFReadL(&gp_header, sizeof(GP_PK_HEADER), 1, fin) != 1 ||
352 0 : VSIFReadL(&sub_header, sizeof(GP_PK_SH1), 1, fin) != 1 ||
353 0 : VSIFReadL(&visir_line, sizeof(SUB_VISIRLINE), 1, fin) != 1)
354 : {
355 0 : _open_success = false;
356 0 : break;
357 : }
358 0 : to_native(visir_line);
359 0 : to_native(gp_header);
360 :
361 0 : CPLDebugOnly("MSGN",
362 : "channelId = %d, lineNumber = %d, packetLength = %u",
363 : visir_line.channelId, visir_line.lineNumberInVisirGrid,
364 : gp_header.packetLength);
365 :
366 0 : to_native(sub_header);
367 :
368 0 : CPLDebugOnly("MSGN",
369 : "subheader spacecraft = %d, day = %u, sec = %.3f",
370 : sub_header.spacecraftId, sub_header.packetTime.day,
371 : sub_header.packetTime.ms / 1000.0);
372 :
373 : // Sanity checks
374 0 : if (gp_header.packetLength <
375 0 : sizeof(GP_PK_SH1) + sizeof(SUB_VISIRLINE) - 1 ||
376 0 : gp_header.packetLength > 100 * 1024 * 1024)
377 : {
378 0 : _open_success = false;
379 0 : break;
380 : }
381 :
382 : // skip over the actual line data
383 0 : CPL_IGNORE_RET_VAL(
384 0 : VSIFSeekL(fin,
385 0 : static_cast<vsi_l_offset>(gp_header.packetLength) -
386 : (sizeof(GP_PK_SH1) + sizeof(SUB_VISIRLINE) - 1),
387 : SEEK_CUR));
388 :
389 0 : if (visir_line.channelId == 0 ||
390 0 : visir_line.channelId > MSG_NUM_CHANNELS)
391 : {
392 0 : _open_success = false;
393 0 : break;
394 : }
395 :
396 0 : if (scanned_bands[visir_line.channelId - 1])
397 : {
398 0 : scanned_bands[visir_line.channelId - 1] = 0;
399 0 : band_count--;
400 :
401 0 : if (visir_line.channelId != 12)
402 : { // not the HRV channel
403 0 : _visir_bytes_per_line =
404 0 : gp_header.packetLength -
405 : (unsigned int)(sizeof(GP_PK_SH1) + sizeof(SUB_VISIRLINE) -
406 : 1);
407 0 : _visir_packet_size = gp_header.packetLength +
408 0 : (unsigned int)sizeof(GP_PK_HEADER) + 1;
409 0 : _interline_spacing += _visir_packet_size;
410 : }
411 : else
412 : {
413 0 : _hrv_bytes_per_line = gp_header.packetLength -
414 : (unsigned int)(sizeof(GP_PK_SH1) +
415 : sizeof(SUB_VISIRLINE) - 1);
416 0 : _hrv_packet_size = gp_header.packetLength +
417 0 : (unsigned int)sizeof(GP_PK_HEADER) + 1;
418 0 : _interline_spacing += _hrv_packet_size;
419 :
420 : // The HRV channel has 3 consecutive lines
421 0 : const int lineNumberInVisirGrid =
422 : visir_line.lineNumberInVisirGrid;
423 0 : const auto packetLength = gp_header.packetLength;
424 0 : for (int extraLines = 0; extraLines < 2; extraLines++)
425 : {
426 0 : if (VSIFReadL(&gp_header, sizeof(GP_PK_HEADER), 1, fin) !=
427 0 : 1 ||
428 0 : VSIFReadL(&sub_header, sizeof(GP_PK_SH1), 1, fin) !=
429 0 : 1 ||
430 0 : VSIFReadL(&visir_line, sizeof(SUB_VISIRLINE), 1, fin) !=
431 : 1)
432 : {
433 0 : _open_success = false;
434 0 : return;
435 : }
436 0 : to_native(visir_line);
437 0 : to_native(gp_header);
438 :
439 0 : CPLDebugOnly(
440 : "MSGN",
441 : "channelId = %d, lineNumber = %d, packetLength = %u",
442 : visir_line.channelId, visir_line.lineNumberInVisirGrid,
443 : gp_header.packetLength);
444 :
445 0 : if (visir_line.channelId != 12 ||
446 0 : visir_line.lineNumberInVisirGrid !=
447 0 : lineNumberInVisirGrid + extraLines + 1 ||
448 0 : gp_header.packetLength != packetLength)
449 : {
450 0 : CPLDebugOnly("MSGN", "Inconsistent records");
451 0 : _open_success = false;
452 0 : return;
453 : }
454 :
455 : // skip over the actual line data
456 0 : CPL_IGNORE_RET_VAL(VSIFSeekL(
457 : fin,
458 0 : static_cast<vsi_l_offset>(gp_header.packetLength) -
459 : (sizeof(GP_PK_SH1) + sizeof(SUB_VISIRLINE) - 1),
460 : SEEK_CUR));
461 :
462 0 : _interline_spacing += _hrv_packet_size;
463 : }
464 : }
465 : }
466 0 : } while (band_count > 0);
467 :
468 : TRAILER trailer;
469 :
470 0 : CPL_IGNORE_RET_VAL(
471 0 : VSIFSeekL(fin, static_cast<vsi_l_offset>(_f_trailer_offset), SEEK_SET));
472 :
473 0 : if (VSIFReadL(&gp_header, sizeof(GP_PK_HEADER), 1, fin) != 1 ||
474 0 : VSIFReadL(&sub_header, sizeof(GP_PK_SH1), 1, fin) != 1 ||
475 0 : VSIFReadL(&trailer, sizeof(TRAILER), 1, fin) != 1)
476 : {
477 0 : _open_success = false;
478 0 : fprintf(stderr, "Trailer fail\n"); /*ok*/
479 0 : return;
480 : }
481 :
482 0 : to_native(trailer.imageProductionStats.actualL15CoverageVisir);
483 0 : to_native(trailer.imageProductionStats.actualL15CoverageHrv);
484 :
485 0 : CPLDebugOnly("MSGN", "Trailer Version %d, satellite %d",
486 : trailer.trailerHeaderVersion,
487 : trailer.imageProductionStats.satelliteId);
488 :
489 0 : CPLDebugOnly(
490 : "MSGN",
491 : "\nactualL15CoverageVisir.SouthernLineActual = %d, \n"
492 : "actualL15CoverageVisir.NorthernLineActual = %d, \n"
493 : "actualL15CoverageVisir.EasternColumnActual = %d, \n "
494 : "actualL15CoverageVisir.WesternColumnActual = %d",
495 : trailer.imageProductionStats.actualL15CoverageVisir.southernLineActual,
496 : trailer.imageProductionStats.actualL15CoverageVisir.northernLineActual,
497 : trailer.imageProductionStats.actualL15CoverageVisir.easternColumnActual,
498 : trailer.imageProductionStats.actualL15CoverageVisir
499 : .westernColumnActual);
500 :
501 0 : CPLDebugOnly(
502 : "MSGN",
503 : "\nactualCoverage_hrv.lowerSouthLineActual = %d, \n"
504 : "actualCoverage_hrv.lowerNorthLineActual = %d, \n"
505 : "actualCoverage_hrv.lowerEastColumnActual = %d, \n "
506 : "actualCoverage_hrv.lowerWestColumnActual = %d",
507 : trailer.imageProductionStats.actualL15CoverageHrv.lowerSouthLineActual,
508 : trailer.imageProductionStats.actualL15CoverageHrv.lowerNorthLineActual,
509 : trailer.imageProductionStats.actualL15CoverageHrv.lowerEastColumnActual,
510 : trailer.imageProductionStats.actualL15CoverageHrv
511 : .lowerWestColumnActual);
512 :
513 0 : CPLDebugOnly(
514 : "MSGN",
515 : "\nactualCoverage_hrv.upperSouthLineActual = %d, \n"
516 : "actualCoverage_hrv.upperNorthLineActual = %d, \n"
517 : "actualCoverage_hrv.upperEastColumnActual = %d, \n "
518 : "actualCoverage_hrv.upperWestColumnActual = %d",
519 : trailer.imageProductionStats.actualL15CoverageHrv.upperSouthLineActual,
520 : trailer.imageProductionStats.actualL15CoverageHrv.upperNorthLineActual,
521 : trailer.imageProductionStats.actualL15CoverageHrv.upperEastColumnActual,
522 : trailer.imageProductionStats.actualL15CoverageHrv
523 : .upperWestColumnActual);
524 : }
525 :
526 : #ifndef GDAL_SUPPORT
527 :
528 : int Msg_reader_core::_chan_to_idx(Msg_channel_names channel)
529 : {
530 : unsigned int idx = 0;
531 : while (idx < MSG_NUM_CHANNELS)
532 : {
533 : if ((1 << (idx + 1)) == (int)channel)
534 : {
535 : return idx;
536 : }
537 : idx++;
538 : }
539 : return 0;
540 : }
541 :
542 : void Msg_reader_core::get_pixel_geo_coordinates(unsigned int line,
543 : unsigned int column,
544 : double &longitude,
545 : double &latitude) const
546 : {
547 : Conversions::convert_pixel_to_geo((double)(line + _line_start),
548 : (double)(column + _col_start), longitude,
549 : latitude);
550 : longitude += _img_desc_record.longitudeOfSSP;
551 : }
552 :
553 : void Msg_reader_core::get_pixel_geo_coordinates(double line, double column,
554 : double &longitude,
555 : double &latitude)
556 : {
557 : Conversions::convert_pixel_to_geo(line + _line_start, column + _col_start,
558 : longitude, latitude);
559 : longitude += _img_desc_record.longitudeOfSSP;
560 : }
561 :
562 : double Msg_reader_core::compute_pixel_area_sqkm(double line, double column)
563 : {
564 : return Conversions::compute_pixel_area_sqkm(line + _line_start,
565 : column + _col_start);
566 : }
567 :
568 : #endif // GDAL_SUPPORT
569 :
570 : } // namespace msg_native_format
|