LCOV - code coverage report
Current view: top level - frmts/msgn - msg_reader_core.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 0 189 0.0 %
Date: 2024-04-27 17:22:41 Functions: 0 5 0.0 %

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

Generated by: LCOV version 1.14