LCOV - code coverage report
Current view: top level - gcore - geoheif.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 0 122 0.0 %
Date: 2025-01-18 12:42:00 Functions: 0 14 0.0 %

          Line data    Source code
       1             : /**********************************************************************
       2             :  *
       3             :  * Name:     geoheif.cpp
       4             :  * Project:  GDAL
       5             :  * Purpose:  OGC GeoHEIF shared implementation.
       6             :  * Author:   Brad Hards <bradh@silvereye.tech>
       7             :  *
       8             :  **********************************************************************
       9             :  * Copyright (c) 2024, Brad Hards
      10             :  *
      11             :  * SPDX-License-Identifier: MIT
      12             :  ****************************************************************************/
      13             : #include "geoheif.h"
      14             : 
      15             : namespace gdal
      16             : {
      17             : 
      18             : //! @cond Doxygen_Suppress
      19             : 
      20           0 : GeoHEIF::GeoHEIF() : gcps(0)
      21             : {
      22           0 : }
      23             : 
      24           0 : GeoHEIF::~GeoHEIF()
      25             : {
      26           0 : }
      27             : 
      28           0 : bool GeoHEIF::has_SRS() const
      29             : {
      30           0 :     return !m_oSRS.IsEmpty();
      31             : }
      32             : 
      33           0 : bool GeoHEIF::has_GCPs() const
      34             : {
      35           0 :     return haveGCPs;
      36             : }
      37             : 
      38           0 : static double to_double(const uint8_t *data, uint32_t index)
      39             : {
      40           0 :     double d = 0;
      41           0 :     memcpy(&d, data + index, sizeof(d));
      42           0 :     CPL_MSBPTR64(&d);
      43           0 :     return d;
      44             : }
      45             : 
      46           0 : static double int_as_double(const uint8_t *data, uint32_t index)
      47             : {
      48           0 :     uint32_t v = 0;
      49           0 :     memcpy(&v, data + index, sizeof(uint32_t));
      50           0 :     CPL_MSBPTR32(&v);
      51           0 :     return static_cast<double>(v);
      52             : }
      53             : 
      54           0 : void GeoHEIF::setModelTransformation(const uint8_t *payload, size_t length)
      55             : {
      56             :     // TODO: this only handles the 2D case.
      57           0 :     if (length != (6 * 8 + 4))
      58             :     {
      59           0 :         return;
      60             :     }
      61             :     // Match version
      62           0 :     if (payload[0] == 0x00)
      63             :     {
      64           0 :         uint32_t index = 0;
      65           0 :         if (payload[index + 3] == 0x01)
      66             :         {
      67           0 :             index += 4;
      68           0 :             modelTransform[1] = to_double(payload, index);
      69           0 :             index += 8;
      70           0 :             modelTransform[2] = to_double(payload, index);
      71           0 :             index += 8;
      72           0 :             modelTransform[0] = to_double(payload, index);
      73           0 :             index += 8;
      74           0 :             modelTransform[4] = to_double(payload, index);
      75           0 :             index += 8;
      76           0 :             modelTransform[5] = to_double(payload, index);
      77           0 :             index += 8;
      78           0 :             modelTransform[3] = to_double(payload, index);
      79             :         }
      80             :     }
      81             :     else
      82             :     {
      83           0 :         CPLDebug("GeoHEIF", "Unsupported mtxf version %d", payload[0]);
      84             :     }
      85             : }
      86             : 
      87           0 : CPLErr GeoHEIF::GetGeoTransform(double *padfTransform) const
      88             : {
      89             :     std::vector<int> axes =
      90           0 :         has_SRS() ? m_oSRS.GetDataAxisToSRSAxisMapping() : std::vector<int>();
      91             : 
      92           0 :     if (axes.size() && axes[0] != 1)
      93             :     {
      94           0 :         padfTransform[1] = modelTransform[4];
      95           0 :         padfTransform[2] = modelTransform[5];
      96           0 :         padfTransform[0] = modelTransform[3];
      97           0 :         padfTransform[4] = modelTransform[1];
      98           0 :         padfTransform[5] = modelTransform[2];
      99           0 :         padfTransform[3] = modelTransform[0];
     100             :     }
     101             :     else
     102             :     {
     103           0 :         padfTransform[1] = modelTransform[1];
     104           0 :         padfTransform[2] = modelTransform[2];
     105           0 :         padfTransform[0] = modelTransform[0];
     106           0 :         padfTransform[4] = modelTransform[4];
     107           0 :         padfTransform[5] = modelTransform[5];
     108           0 :         padfTransform[3] = modelTransform[3];
     109             :     }
     110           0 :     return CE_None;
     111             : }
     112             : 
     113             : /************************************************************************/
     114             : /*                          GetSpatialRef()                             */
     115             : /************************************************************************/
     116           0 : const OGRSpatialReference *GeoHEIF::GetSpatialRef() const
     117             : {
     118           0 :     return !m_oSRS.IsEmpty() ? &m_oSRS : nullptr;
     119             : }
     120             : 
     121           0 : void GeoHEIF::extractSRS(const uint8_t *payload, size_t length) const
     122             : {
     123             :     // TODO: more sophisticated length checks
     124           0 :     if (length < 12)
     125             :     {
     126           0 :         CPLDebug("GeoHEIF", "Infeasible length CRS payload %u",
     127             :                  static_cast<unsigned>(length));
     128           0 :         return;
     129             :     }
     130           0 :     std::string crsEncoding(payload + 4, payload + 8);
     131           0 :     std::string crs(payload + 8, payload + length);
     132           0 :     if (crsEncoding == "wkt2")
     133             :     {
     134           0 :         m_oSRS.importFromWkt(crs.c_str());
     135             :     }
     136           0 :     else if (crsEncoding == "crsu")
     137             :     {
     138           0 :         m_oSRS.importFromCRSURL(crs.c_str());
     139             :     }
     140           0 :     else if (crsEncoding == "curi")
     141             :     {
     142             :         // null terminated string in the form "[EPSG:4326]"
     143           0 :         if ((crs.at(0) != '[') || (crs.at(crs.length() - 2) != ']') ||
     144           0 :             (crs.at(crs.length() - 1) != '\0'))
     145             :         {
     146           0 :             CPLDebug("GeoHEIF", "CRS CURIE is not a safe CURIE");
     147           0 :             return;
     148             :         }
     149           0 :         std::string curie = crs.substr(1, crs.length() - 3);
     150           0 :         size_t separatorPos = curie.find(':');
     151           0 :         if (separatorPos == std::string::npos)
     152             :         {
     153           0 :             CPLDebug("GeoHEIF",
     154             :                      "CRS CURIE does not contain required separator");
     155           0 :             return;
     156             :         }
     157           0 :         std::string authority = curie.substr(0, separatorPos);
     158           0 :         std::string code = curie.substr(separatorPos + 1);
     159           0 :         std::string osURL("http://www.opengis.net/def/crs/");
     160           0 :         osURL.append(authority);
     161           0 :         osURL += "/0/";
     162           0 :         osURL.append(code);
     163           0 :         m_oSRS.importFromCRSURL(osURL.c_str());
     164             :     }
     165             :     else
     166             :     {
     167           0 :         CPLDebug("GeoHEIF", "CRS encoding is not supported");
     168           0 :         return;
     169             :     }
     170           0 :     m_oSRS.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
     171             : }
     172             : 
     173           0 : void GeoHEIF::addGCPs(const uint8_t *data, size_t length)
     174             : {
     175           0 :     constexpr size_t MIN_VALID_SIZE = sizeof(uint32_t) + sizeof(uint16_t) +
     176             :                                       2 * sizeof(uint32_t) + 2 * sizeof(double);
     177           0 :     if (length < MIN_VALID_SIZE)
     178             :     {
     179           0 :         CPLDebug("GeoHEIF", "GCP data length is too short");
     180           0 :         return;
     181             :     }
     182           0 :     if (data[0] == 0x00)
     183             :     {
     184           0 :         uint32_t index = 0;
     185           0 :         bool is_3D = (data[index + 3] == 0x00);
     186           0 :         if (is_3D)
     187             :         {
     188           0 :             if (length < MIN_VALID_SIZE + sizeof(double))
     189             :             {
     190           0 :                 CPLDebug("GeoHEIF", "GCP data length is too short for 3D");
     191           0 :                 return;
     192             :             }
     193             :         }
     194           0 :         index += sizeof(uint32_t);
     195           0 :         uint16_t count = (data[index] << 8) + (data[index + 1]);
     196           0 :         index += sizeof(uint16_t);
     197           0 :         for (uint16_t j = 0; (j < count) && (index < length); j++)
     198             :         {
     199           0 :             double dfGCPPixel = int_as_double(data, index);
     200           0 :             index += sizeof(uint32_t);
     201           0 :             double dfGCPLine = int_as_double(data, index);
     202           0 :             index += sizeof(uint32_t);
     203           0 :             double dfGCPX = to_double(data, index);
     204           0 :             index += sizeof(double);
     205           0 :             double dfGCPY = to_double(data, index);
     206           0 :             index += sizeof(double);
     207           0 :             double dfGCPZ = 0.0;
     208           0 :             if (is_3D)
     209             :             {
     210           0 :                 dfGCPZ = to_double(data, index);
     211           0 :                 index += sizeof(double);
     212             :             }
     213             :             gcps.emplace_back("", "", dfGCPPixel, dfGCPLine, dfGCPX, dfGCPY,
     214           0 :                               dfGCPZ);
     215           0 :             haveGCPs = true;
     216             :         }
     217             :     }
     218             :     else
     219             :     {
     220           0 :         CPLDebug("GeoHEIF", "Unsupported tiep version %d", data[0]);
     221             :     }
     222             : }
     223             : 
     224           0 : int GeoHEIF::GetGCPCount() const
     225             : {
     226           0 :     return static_cast<int>(gcps.size());
     227             : }
     228             : 
     229           0 : const GDAL_GCP *GeoHEIF::GetGCPs()
     230             : {
     231           0 :     return gdal::GCP::c_ptr(gcps);
     232             : }
     233             : 
     234           0 : const OGRSpatialReference *GeoHEIF::GetGCPSpatialRef() const
     235             : {
     236           0 :     return this->GetSpatialRef();
     237             : }
     238             : 
     239             : }  // namespace gdal
     240             : 
     241             : //! @endcond

Generated by: LCOV version 1.14