LCOV - code coverage report
Current view: top level - gcore - tiff_common.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 94 100 94.0 %
Date: 2025-01-18 12:42:00 Functions: 3 3 100.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  GDAL Core
       4             :  * Purpose:  Common code shared between the GTiff and libertiff drivers
       5             :  * Author:   Even Rouault <even dot rouault at spatialys.com>
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 2024, Even Rouault <even dot rouault at spatialys.com>
       9             :  *
      10             :  * SPDX-License-Identifier: MIT
      11             :  ****************************************************************************/
      12             : 
      13             : #include "tiff_common.h"
      14             : 
      15             : #include <algorithm>
      16             : 
      17             : #include "gdal_mdreader.h"
      18             : 
      19             : namespace gdal
      20             : {
      21             : namespace tiff_common
      22             : {
      23             : 
      24             : /************************************************************************/
      25             : /*                       PrepareTIFFErrorFormat()                       */
      26             : /*                                                                      */
      27             : /*      sometimes the "module" has stuff in it that has special         */
      28             : /*      meaning in a printf() style format, so we try to escape it.     */
      29             : /*      For now we hope the only thing we have to escape is %'s.        */
      30             : /************************************************************************/
      31             : 
      32         588 : char *PrepareTIFFErrorFormat(const char *module, const char *fmt)
      33             : 
      34             : {
      35         588 :     const size_t nModuleSize = strlen(module);
      36         588 :     const size_t nModFmtSize = nModuleSize * 2 + strlen(fmt) + 2;
      37         588 :     char *pszModFmt = static_cast<char *>(CPLMalloc(nModFmtSize));
      38             : 
      39         588 :     size_t iOut = 0;  // Used after for.
      40             : 
      41        9737 :     for (size_t iIn = 0; iIn < nModuleSize; ++iIn)
      42             :     {
      43        9149 :         if (module[iIn] == '%')
      44             :         {
      45           0 :             CPLAssert(iOut < nModFmtSize - 2);
      46           0 :             pszModFmt[iOut++] = '%';
      47           0 :             pszModFmt[iOut++] = '%';
      48             :         }
      49             :         else
      50             :         {
      51        9149 :             CPLAssert(iOut < nModFmtSize - 1);
      52        9149 :             pszModFmt[iOut++] = module[iIn];
      53             :         }
      54             :     }
      55         588 :     CPLAssert(iOut < nModFmtSize);
      56         588 :     pszModFmt[iOut] = '\0';
      57         588 :     strcat(pszModFmt, ":");
      58         588 :     strcat(pszModFmt, fmt);
      59             : 
      60         588 :     return pszModFmt;
      61             : }
      62             : 
      63             : /************************************************************************/
      64             : /*                     TIFFColorMapTagToColorTable()                    */
      65             : /************************************************************************/
      66             : 
      67         150 : std::unique_ptr<GDALColorTable> TIFFColorMapTagToColorTable(
      68             :     const unsigned short *panRed, const unsigned short *panGreen,
      69             :     const unsigned short *panBlue, int nColorCount, int &nColorTableMultiplier,
      70             :     int nDefaultColorTableMultiplier, bool bNoDataSet, double dfNoDataValue)
      71             : {
      72         150 :     auto poColorTable = std::make_unique<GDALColorTable>();
      73             : 
      74         150 :     if (nColorTableMultiplier == 0)
      75             :     {
      76             :         // TIFF color maps are in the [0, 65535] range, so some remapping must
      77             :         // be done to get values in the [0, 255] range, but it is not clear
      78             :         // how to do that exactly. Since GDAL 2.3.0 we have standardized on
      79             :         // using a 257 multiplication factor (https://github.com/OSGeo/gdal/commit/eeec5b62e385d53e7f2edaba7b73c7c74bc2af39)
      80             :         // but other software uses 256 (cf https://github.com/OSGeo/gdal/issues/10310)
      81             :         // Do a first pass to check if all values are multiples of 256 or 257.
      82         139 :         bool bFoundNonZeroEntry = false;
      83         139 :         bool bAllValuesMultipleOf256 = true;
      84         139 :         bool bAllValuesMultipleOf257 = true;
      85         139 :         unsigned short nMaxColor = 0;
      86      293287 :         for (int iColor = 0; iColor < nColorCount; ++iColor)
      87             :         {
      88      293148 :             if (panRed[iColor] > 0 || panGreen[iColor] > 0 ||
      89      284833 :                 panBlue[iColor] > 0)
      90             :             {
      91        8414 :                 bFoundNonZeroEntry = true;
      92             :             }
      93      293148 :             if ((panRed[iColor] % 256) != 0 || (panGreen[iColor] % 256) != 0 ||
      94      284835 :                 (panBlue[iColor] % 256) != 0)
      95             :             {
      96        8412 :                 bAllValuesMultipleOf256 = false;
      97             :             }
      98      293148 :             if ((panRed[iColor] % 257) != 0 || (panGreen[iColor] % 257) != 0 ||
      99      293146 :                 (panBlue[iColor] % 257) != 0)
     100             :             {
     101           2 :                 bAllValuesMultipleOf257 = false;
     102             :             }
     103             : 
     104      293148 :             nMaxColor = std::max(nMaxColor, panRed[iColor]);
     105      293148 :             nMaxColor = std::max(nMaxColor, panGreen[iColor]);
     106      293148 :             nMaxColor = std::max(nMaxColor, panBlue[iColor]);
     107             :         }
     108             : 
     109         139 :         if (nMaxColor > 0 && nMaxColor < 256)
     110             :         {
     111             :             // Bug 1384 - Some TIFF files are generated with color map entry
     112             :             // values in range 0-255 instead of 0-65535 - try to handle these
     113             :             // gracefully.
     114           0 :             nColorTableMultiplier = 1;
     115           0 :             CPLDebug("GTiff",
     116             :                      "TIFF ColorTable seems to be improperly scaled with "
     117             :                      "values all in [0,255] range, fixing up.");
     118             :         }
     119             :         else
     120             :         {
     121         139 :             if (!bAllValuesMultipleOf256 && !bAllValuesMultipleOf257)
     122             :             {
     123           0 :                 CPLDebug("GTiff",
     124             :                          "The color map contains entries which are not "
     125             :                          "multiple of 256 or 257, so we don't know for "
     126             :                          "sure how to remap them to [0, 255]. Default to "
     127             :                          "using a 257 multiplication factor");
     128             :             }
     129         139 :             nColorTableMultiplier =
     130         138 :                 (bFoundNonZeroEntry && bAllValuesMultipleOf256)
     131         277 :                     ? 256
     132             :                     : nDefaultColorTableMultiplier;
     133             :         }
     134             :     }
     135         150 :     CPLAssert(nColorTableMultiplier > 0);
     136         150 :     CPLAssert(nColorTableMultiplier <= 257);
     137      360378 :     for (int iColor = nColorCount - 1; iColor >= 0; iColor--)
     138             :     {
     139             :         const GDALColorEntry oEntry = {
     140      360228 :             static_cast<short>(panRed[iColor] / nColorTableMultiplier),
     141      360228 :             static_cast<short>(panGreen[iColor] / nColorTableMultiplier),
     142      360228 :             static_cast<short>(panBlue[iColor] / nColorTableMultiplier),
     143             :             static_cast<short>(
     144        4096 :                 bNoDataSet && static_cast<int>(dfNoDataValue) == iColor ? 0
     145      364324 :                                                                         : 255)};
     146             : 
     147      360228 :         poColorTable->SetColorEntry(iColor, &oEntry);
     148             :     }
     149             : 
     150         150 :     return poColorTable;
     151             : }
     152             : 
     153             : /************************************************************************/
     154             : /*                      TIFFRPCTagToRPCMetadata()                       */
     155             : /************************************************************************/
     156             : 
     157          38 : CPLStringList TIFFRPCTagToRPCMetadata(const double adfRPC[92])
     158             : {
     159          38 :     CPLStringList asMD;
     160          38 :     asMD.SetNameValue(RPC_ERR_BIAS, CPLOPrintf("%.15g", adfRPC[0]));
     161          38 :     asMD.SetNameValue(RPC_ERR_RAND, CPLOPrintf("%.15g", adfRPC[1]));
     162          38 :     asMD.SetNameValue(RPC_LINE_OFF, CPLOPrintf("%.15g", adfRPC[2]));
     163          38 :     asMD.SetNameValue(RPC_SAMP_OFF, CPLOPrintf("%.15g", adfRPC[3]));
     164          38 :     asMD.SetNameValue(RPC_LAT_OFF, CPLOPrintf("%.15g", adfRPC[4]));
     165          38 :     asMD.SetNameValue(RPC_LONG_OFF, CPLOPrintf("%.15g", adfRPC[5]));
     166          38 :     asMD.SetNameValue(RPC_HEIGHT_OFF, CPLOPrintf("%.15g", adfRPC[6]));
     167          38 :     asMD.SetNameValue(RPC_LINE_SCALE, CPLOPrintf("%.15g", adfRPC[7]));
     168          38 :     asMD.SetNameValue(RPC_SAMP_SCALE, CPLOPrintf("%.15g", adfRPC[8]));
     169          38 :     asMD.SetNameValue(RPC_LAT_SCALE, CPLOPrintf("%.15g", adfRPC[9]));
     170          38 :     asMD.SetNameValue(RPC_LONG_SCALE, CPLOPrintf("%.15g", adfRPC[10]));
     171          38 :     asMD.SetNameValue(RPC_HEIGHT_SCALE, CPLOPrintf("%.15g", adfRPC[11]));
     172             : 
     173          76 :     CPLString osField;
     174          76 :     CPLString osMultiField;
     175             : 
     176         798 :     for (int i = 0; i < 20; ++i)
     177             :     {
     178         760 :         osField.Printf("%.15g", adfRPC[12 + i]);
     179         760 :         if (i > 0)
     180         722 :             osMultiField += " ";
     181             :         else
     182          38 :             osMultiField = "";
     183         760 :         osMultiField += osField;
     184             :     }
     185          38 :     asMD.SetNameValue(RPC_LINE_NUM_COEFF, osMultiField);
     186             : 
     187         798 :     for (int i = 0; i < 20; ++i)
     188             :     {
     189         760 :         osField.Printf("%.15g", adfRPC[32 + i]);
     190         760 :         if (i > 0)
     191         722 :             osMultiField += " ";
     192             :         else
     193          38 :             osMultiField = "";
     194         760 :         osMultiField += osField;
     195             :     }
     196          38 :     asMD.SetNameValue(RPC_LINE_DEN_COEFF, osMultiField);
     197             : 
     198         798 :     for (int i = 0; i < 20; ++i)
     199             :     {
     200         760 :         osField.Printf("%.15g", adfRPC[52 + i]);
     201         760 :         if (i > 0)
     202         722 :             osMultiField += " ";
     203             :         else
     204          38 :             osMultiField = "";
     205         760 :         osMultiField += osField;
     206             :     }
     207          38 :     asMD.SetNameValue(RPC_SAMP_NUM_COEFF, osMultiField);
     208             : 
     209         798 :     for (int i = 0; i < 20; ++i)
     210             :     {
     211         760 :         osField.Printf("%.15g", adfRPC[72 + i]);
     212         760 :         if (i > 0)
     213         722 :             osMultiField += " ";
     214             :         else
     215          38 :             osMultiField = "";
     216         760 :         osMultiField += osField;
     217             :     }
     218          38 :     asMD.SetNameValue(RPC_SAMP_DEN_COEFF, osMultiField);
     219          76 :     return asMD;
     220             : }
     221             : 
     222             : }  // namespace tiff_common
     223             : }  // namespace gdal

Generated by: LCOV version 1.14